module Morph
Constants
- VERSION
Public Class Methods
classes()
click to toggle source
# File lib/morph.rb, line 130 def classes Chas.morph_classes end
from_csv(csv, class_name, namespace=Morph)
click to toggle source
# File lib/morph.rb, line 150 def from_csv csv, class_name, namespace=Morph objects = [] CSV.parse(csv, { :headers => true }) do |row| object = object_from_name class_name, namespace row.each do |key, value| object.morph(key, value) end objects << object end objects end
from_hash(hash, namespace=Morph)
click to toggle source
# File lib/morph.rb, line 190 def from_hash hash, namespace=Morph if hash.keys.size == 1 name = hash.keys.first case hash[name] when Hash object_from_hash hash[name], name, namespace when Array objects_from_array hash[name], name, namespace else raise 'hash root value must be a Hash or an Array' end else raise 'hash must have single key' end end
from_json(json, root_key=nil, namespace=Morph)
click to toggle source
# File lib/morph.rb, line 183 def from_json json, root_key=nil, namespace=Morph require 'json' unless defined? JSON hash = JSON.parse json hash = { root_key => hash } if root_key from_hash hash, namespace end
from_tsv(tsv, class_name, namespace=Morph)
click to toggle source
# File lib/morph.rb, line 162 def from_tsv tsv, class_name, namespace=Morph lines = tsv.split("\n") attributes = lines[0].split("\t") lines = lines[1..(lines.length-1)] objects = [] lines.each do |line| values = line.split("\t") object = object_from_name class_name, namespace attributes.each_with_index do |attribute, index| object.morph(attribute, values[index]) end objects << object end objects end
from_xml(xml, namespace=Morph)
click to toggle source
# File lib/morph.rb, line 178 def from_xml xml, namespace=Morph hash = Hash.from_xml xml from_hash hash, namespace end
generate_migrations(object, options={})
click to toggle source
# File lib/morph.rb, line 142 def generate_migrations object, options={} options[:ignore] ||= [] options[:belongs_to_id] ||= '' migrations = [] name = object.class.name.demodulize.underscore add_migration name, object.morph_attributes, migrations, options end
included(base)
click to toggle source
# File lib/morph.rb, line 216 def included(base) base.extend ClassMethods base.send(:include, MethodMissing) end
register_listener(listener)
click to toggle source
# File lib/morph.rb, line 134 def register_listener listener Chas.register_listener listener end
script_generate(morphed_class, options={}) { |name| ... }
click to toggle source
# File lib/morph.rb, line 207 def script_generate morphed_class, options={} name = morphed_class.name.to_s.split('::').last name = yield name if block_given? generator = options[:generator] || 'model' line = ["rails destroy #{generator} #{name}; rails generate #{generator} #{name}"] morphed_class.morph_methods.select{|m| not(m =~ /=$/) }.each {|attribute| line << " #{attribute}:string"} line.join('') end
unregister_listener(listener)
click to toggle source
# File lib/morph.rb, line 138 def unregister_listener listener Chas.unregister_listener listener end
Private Class Methods
add_migration(name, attributes, migrations, options)
click to toggle source
# File lib/morph.rb, line 222 def add_migration name, attributes, migrations, options migration = "./script/generate model #{name}#{options[:belongs_to_id]}" options[:belongs_to_id] = '' migrations << migration attributes = [attributes] if attributes.is_a?(String) attributes.to_a.sort{|a,b| a[0].to_s <=> b[0].to_s}.each do |attribute, value| case value when String attribute_name = attribute.to_s unless options[:ignore].include?(attribute_name) type = attribute_name[/date$/] ? 'date' : 'string' attribute_def = "#{attribute}:#{type}" migration.sub!(migration, "#{migration} #{attribute_def}") end when Array options[:belongs_to_id] = " #{name}_id:integer" migrations = add_migration(attribute, '', migrations, options) when Hash options[:belongs_to_id] = " #{name}_id:integer" migrations = add_migration(attribute, value, migrations, options) when nil # ignore else puts 'not supported ' + value.inspect end end migrations end
add_to_object(object, attributes, namespace)
click to toggle source
# File lib/morph.rb, line 280 def add_to_object object, attributes, namespace attributes.each do |name, value| name = name.to_s if name.is_a?(Symbol) attribute = name.gsub(':',' ').underscore value = value.to_time if defined?(XMLRPC::DateTime) && value.is_a?(XMLRPC::DateTime) case value when String, Date, Time, TrueClass, FalseClass, Integer, Float object.morph(attribute, value) when Array attribute = attribute.pluralize object.morph(attribute, objects_from_array(value, name, namespace)) when Hash object.morph(attribute, object_from_hash(value, name, namespace)) when NilClass object.morph(attribute, nil) else raise "cannot handle adding #{name} value of class: #{value.class.name}" end end object end
class_constant(namespace, name)
click to toggle source
# File lib/morph.rb, line 250 def class_constant namespace, name "#{namespace.name}::#{name}".constantize end
object_from_hash(hash, name, namespace)
click to toggle source
# File lib/morph.rb, line 266 def object_from_hash hash, name, namespace object = object_from_name(name, namespace) add_to_object(object, hash, namespace) end
object_from_name(name, namespace)
click to toggle source
# File lib/morph.rb, line 254 def object_from_name name, namespace name = Chas.convert_to_morph_class_name(name).camelize begin type = class_constant namespace, name rescue NameError => e namespace.const_set name, Class.new type = class_constant namespace, name type.send(:include, Morph) end type.new end
objects_from_array(array, name, namespace)
click to toggle source
# File lib/morph.rb, line 271 def objects_from_array array, name, namespace if array.size > 0 && array.collect(&:class).uniq == [Hash] name = name.to_s.singularize array.map! { |hash| object_from_hash(hash, name, namespace) } else array end end
Public Instance Methods
morph(attributes_or_label, value=nil)
click to toggle source
Set attribute value(s). Adds accessor methods to class if they are not already present.
Can be called with a string
and a value, a symbol
and a value, or with a hash
of attribute to value pairs. For example.
require 'rubygems'; require 'morph' class Order; include Morph; end order = Order.new order.morph :drink => 'tea', :sugars => 2, 'milk' => 'yes please' order.morph 'Payment type:', 'will wash dishes' order.morph :lemon, false p order # -> #<Order:0x33c50c @lemon=false, @milk="yes please", @payment_type="will wash dishes", @sugars=2, @drink="tea">
# File lib/morph.rb, line 358 def morph attributes_or_label, value=nil if attributes_or_label.is_a? Hash attributes_or_label.each { |a, v| morph(a, v) } else attribute = Chas.convert_to_morph_method_name(attributes_or_label) send("#{attribute}=".to_sym, value) end end
morph_attributes()
click to toggle source
# File lib/morph.rb, line 367 def morph_attributes attributes = self.class.morph_attributes.inject({}) do |hash, attribute| unless attribute =~ /=\Z/ symbol = attribute.to_sym value = send(symbol) value.each do |key, v| value[key] = v.morph_attributes if v.respond_to?(:morph_attributes) end if value.is_a? Hash value = value.collect {|v| v.respond_to?(:morph_attributes) ? v.morph_attributes : v } if value.is_a? Array value = value.morph_attributes if value.respond_to? :morph_attributes hash[symbol] = value end hash end end