Class: DataMapper::EmbeddedValue
- Defined in:
- lib/data_mapper/embedded_value.rb
Overview
EmbeddedValue
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
: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"
Constant Summary collapse
- EMBEDDED_PROPERTIES =
[]
Class Method Summary collapse
-
.containing_class ⇒ Object
returns the class in which the EmbeddedValue is declared.
- .define(container, name, options, &block) ⇒ Object
-
.define_property_getter(name, property) ⇒ Object
define embedded property getters.
-
.define_property_setter(name, property) ⇒ Object
define embedded property setters.
- .inherited(base) ⇒ Object
-
.property(name, type, options = {}) ⇒ Object
add an embedded property.
Instance Method Summary collapse
-
#initialize(instance) ⇒ EmbeddedValue
constructor
A new instance of EmbeddedValue.
Constructor Details
#initialize(instance) ⇒ EmbeddedValue
Returns a new instance of EmbeddedValue.
52 53 54 55 |
# File 'lib/data_mapper/embedded_value.rb', line 52 def initialize(instance) @instance = instance @container_prefix = '' end |
Class Method Details
.containing_class ⇒ Object
returns the class in which the EmbeddedValue is declared
107 108 109 110 111 112 113 |
# File 'lib/data_mapper/embedded_value.rb', line 107 def self.containing_class @containing_class || @containing_class = begin tree = name.split('::') tree.pop tree.inject(Object) { |klass, current| klass.const_get(current) } end end |
.define(container, name, options, &block) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/data_mapper/embedded_value.rb', line 115 def self.define(container, name, , &block) , , accessor_name = nil accessor_name = name.to_s = Inflector.camelize(accessor_name) = Class.new(EmbeddedValue) container.const_set(, ) unless container.const_defined?() if [:prefix] container_prefix = [:prefix].kind_of?(String) ? [:prefix] : "#{accessor_name}_" .instance_variable_set('@container_prefix', container_prefix) end .instance_variable_set('@containing_class', container) .instance_variable_set('@container_lazy', !![:lazy]) .instance_variable_set('@container_reader_visibility', [:reader] || [:accessor] || :public) .instance_variable_set('@container_writer_visibility', [:writer] || [:accessor] || :public) .class_eval(&block) if block_given? container.class_eval <<-EOS def #{accessor_name} #{}.new(self) end EOS end |
.define_property_getter(name, property) ⇒ Object
define embedded property getters
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/data_mapper/embedded_value.rb', line 77 def self.define_property_getter(name, property) # :nodoc: # add the method on the embedded class class_eval <<-EOS #{property.reader_visibility.to_s} def #{name} #{"@instance.lazy_load!("+ property.name.inspect + ")" if property.lazy?} @instance.instance_variable_get(#{property.instance_variable_name.inspect}) end EOS # add a shortcut boolean? method if applicable (ex: activated?) if property.type == :boolean class_eval("alias #{property.name}? #{property.name}") end end |
.define_property_setter(name, property) ⇒ Object
define embedded property setters
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/data_mapper/embedded_value.rb', line 95 def self.define_property_setter(name, property) # :nodoc: # add the method on the embedded class class_eval <<-EOS #{property.writer_visibility.to_s} def #{name.to_s.sub(/\?$/, '')}=(value) @instance.instance_variable_set(#{property.instance_variable_name.inspect}, value) end EOS end |
.inherited(base) ⇒ Object
57 58 59 |
# File 'lib/data_mapper/embedded_value.rb', line 57 def self.inherited(base) base.const_set('EMBEDDED_PROPERTIES', []) end |
.property(name, type, options = {}) ⇒ Object
add an embedded property. For more information about how to define properties, visit Property.
62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/data_mapper/embedded_value.rb', line 62 def self.property(name, type, = {}) # set lazy option on the mapping if defined in the embed block [:lazy] ||= @container_lazy [:reader] ||= [:accessor] || @container_reader_visibility [:writer] ||= [:accessor] || @container_writer_visibility property_name = @container_prefix ? @container_prefix + name.to_s : name property = containing_class.property(property_name, type, ) define_property_getter(name, property) define_property_setter(name, property) end |