Class | DataMapper::EmbeddedValue |
In: |
lib/data_mapper/embedded_value.rb
lib/data_mapper/embedded_value.rb |
Parent: | Object |
As an alternative to an extraneous has_one association, EmbeddedValue offers a means to serialize component objects to a table without having to define an entirely new model.
Example:
class Person < DataMapper::Base property :name, :string property :occupation, :string embed :address, :prefix => true do property :street, :string property :city, :string property :state, :string, :size => 2 property :zip_code, :string, :size => 10 def city_state_zip_code "#{city}, #{state} #{zip_code}" end end end
Columns for the Address model will appear in the Person table. Passing :prefix => true will prefix the column name with the parent table‘s name. The default behavior is to use the columns as they are defined. Using the above example, the database table structure will become:
Column Datatype, Options =============================================================== name :string occupation :string address_street :string address_city :string address_state :string, :size => 2 address_zip_code :string, :size => 10
EmbeddedValue‘s become instance methods off of an instance of the parent class and return a sub-class of the parent class.
bob = Person.first(:name => 'Bob') bob.address # => #<Person::Address:0x1a492b8> bob.address.city # => "Pittsburgh" bob.address.city_state_zip_code # => "Pitsburgh, PA 90210"
EMBEDDED_PROPERTIES | = | [] |
EMBEDDED_PROPERTIES | = | [] |
returns the class in which the EmbeddedValue is declared
# File lib/data_mapper/embedded_value.rb, line 109 109: def self.containing_class 110: @containing_class || @containing_class = begin 111: tree = name.split('::') 112: tree.pop 113: tree.inject(Object) { |klass, current| klass.const_get(current) } 114: end 115: end
returns the class in which the EmbeddedValue is declared
# File lib/data_mapper/embedded_value.rb, line 109 109: def self.containing_class 110: @containing_class || @containing_class = begin 111: tree = name.split('::') 112: tree.pop 113: tree.inject(Object) { |klass, current| klass.const_get(current) } 114: end 115: end
# File lib/data_mapper/embedded_value.rb, line 117 117: def self.define(container, name, options, &block) 118: embedded_class, embedded_class_name, accessor_name = nil 119: 120: accessor_name = name.to_s 121: embedded_class_name = Inflector.camelize(accessor_name) 122: embedded_class = Class.new(EmbeddedValue) 123: container.const_set(embedded_class_name, embedded_class) unless container.const_defined?(embedded_class_name) 124: 125: if options[:prefix] 126: container_prefix = options[:prefix].kind_of?(String) ? options[:prefix] : "#{accessor_name}_" 127: embedded_class.instance_variable_set('@container_prefix', container_prefix) 128: end 129: 130: embedded_class.instance_variable_set('@containing_class', container) 131: 132: embedded_class.instance_variable_set('@container_lazy', !!options[:lazy]) 133: embedded_class.instance_variable_set('@container_reader_visibility', options[:reader] || options[:accessor] || :public) 134: embedded_class.instance_variable_set('@container_writer_visibility', options[:writer] || options[:accessor] || :public) 135: 136: embedded_class.class_eval(&block) if block_given? 137: 138: container.class_eval "def \#{accessor_name}\n\#{embedded_class_name}.new(self)\nend\n" 139: end
# File lib/data_mapper/embedded_value.rb, line 117 117: def self.define(container, name, options, &block) 118: embedded_class, embedded_class_name, accessor_name = nil 119: 120: accessor_name = name.to_s 121: embedded_class_name = Inflector.camelize(accessor_name) 122: embedded_class = Class.new(EmbeddedValue) 123: container.const_set(embedded_class_name, embedded_class) unless container.const_defined?(embedded_class_name) 124: 125: if options[:prefix] 126: container_prefix = options[:prefix].kind_of?(String) ? options[:prefix] : "#{accessor_name}_" 127: embedded_class.instance_variable_set('@container_prefix', container_prefix) 128: end 129: 130: embedded_class.instance_variable_set('@containing_class', container) 131: 132: embedded_class.instance_variable_set('@container_lazy', !!options[:lazy]) 133: embedded_class.instance_variable_set('@container_reader_visibility', options[:reader] || options[:accessor] || :public) 134: embedded_class.instance_variable_set('@container_writer_visibility', options[:writer] || options[:accessor] || :public) 135: 136: embedded_class.class_eval(&block) if block_given? 137: 138: container.class_eval "def \#{accessor_name}\n\#{embedded_class_name}.new(self)\nend\n" 139: end
# File lib/data_mapper/embedded_value.rb, line 57 57: def self.inherited(base) 58: base.const_set('EMBEDDED_PROPERTIES', []) 59: end
# File lib/data_mapper/embedded_value.rb, line 57 57: def self.inherited(base) 58: base.const_set('EMBEDDED_PROPERTIES', []) 59: end
# File lib/data_mapper/embedded_value.rb, line 52 52: def initialize(instance) 53: @instance = instance 54: @container_prefix = '' 55: end
# File lib/data_mapper/embedded_value.rb, line 52 52: def initialize(instance) 53: @instance = instance 54: @container_prefix = '' 55: end
add an embedded property. For more information about how to define properties, visit Property.
# File lib/data_mapper/embedded_value.rb, line 62 62: def self.property(name, type, options = {}) 63: # set lazy option on the mapping if defined in the embed block 64: options[:lazy] ||= @container_lazy 65: 66: options[:reader] ||= options[:accessor] || @container_reader_visibility 67: options[:writer] ||= options[:accessor] || @container_writer_visibility 68: 69: property_name = @container_prefix ? @container_prefix + name.to_s : name 70: 71: property = containing_class.property(property_name, type, options) 72: define_property_getter(name, property) 73: define_property_setter(name, property) 74: end
add an embedded property. For more information about how to define properties, visit Property.
# File lib/data_mapper/embedded_value.rb, line 62 62: def self.property(name, type, options = {}) 63: # set lazy option on the mapping if defined in the embed block 64: options[:lazy] ||= @container_lazy 65: 66: options[:reader] ||= options[:accessor] || @container_reader_visibility 67: options[:writer] ||= options[:accessor] || @container_writer_visibility 68: 69: property_name = @container_prefix ? @container_prefix + name.to_s : name 70: 71: property = containing_class.property(property_name, type, options) 72: define_property_getter(name, property) 73: define_property_setter(name, property) 74: end