Attributes
compositions | [R] |
A hash with composition name keys and composition reflection hash values. |
Public Instance methods
Define a composition for this model, with name being the name of the composition. You must provide either a :mapping option or both the :composer and :decomposer options.
Options:
:class |
if using the :mapping option, the class to use, as a Class, |
:composer |
A proc used to define the method that the composition getter method will call to create the composition. |
:decomposer |
A proc used to define the method called before saving the model object, if the composition object exists, which sets the columns in the model object based on the value of the composition object. |
:mapping |
An array where each element is either a symbol or an array of two symbols. A symbol is treated like an array of two symbols where both symbols are the same. The first symbol represents the getter method in the model, and the second symbol represents the getter method in the composition object. Example: # Uses columns year, month, and day in the current model # Uses year, month, and day methods in the composition object {mapping: [:year, :month, :day]} # Uses columns year, month, and day in the current model # Uses y, m, and d methods in the composition object where # for example y in the composition object represents year # in the model object. {mapping: [[:year, :y], [:month, :m], [:day, :d]]} |
# File lib/sequel/plugins/composition.rb 95 def composition(name, opts=OPTS) 96 opts = opts.dup 97 compositions[name] = opts 98 if mapping = opts[:mapping] 99 keys = mapping.map{|k| k.is_a?(Array) ? k.first : k} 100 if !opts[:composer] 101 late_binding_class_option(opts, name) 102 klass = opts[:class] 103 class_proc = proc{klass || constantize(opts[:class_name])} 104 opts[:composer] = proc do 105 if values = keys.map{|k| get_column_value(k)} and values.any?{|v| !v.nil?} 106 class_proc.call.new(*values) 107 else 108 nil 109 end 110 end 111 end 112 if !opts[:decomposer] 113 setter_meths = keys.map{|k| :"#{k}="} 114 cov_methods = mapping.map{|k| k.is_a?(Array) ? k.last : k} 115 setters = setter_meths.zip(cov_methods) 116 opts[:decomposer] = proc do 117 if (o = compositions[name]).nil? 118 setter_meths.each{|sm| set_column_value(sm, nil)} 119 else 120 setters.each{|sm, cm| set_column_value(sm, o.public_send(cm))} 121 end 122 end 123 end 124 end 125 raise(Error, "Must provide :composer and :decomposer options, or :mapping option") unless opts[:composer] && opts[:decomposer] 126 define_composition_accessor(name, opts) 127 end
Define getter and setter methods for the composition object.
# File lib/sequel/plugins/composition.rb 132 def define_composition_accessor(name, opts=OPTS) 133 composer_meth = opts[:composer_method] = Plugins.def_sequel_method(@composition_module, "#{name}_composer", 0, &opts[:composer]) 134 opts[:decomposer_method] = Plugins.def_sequel_method(@composition_module, "#{name}_decomposer", 0, &opts[:decomposer]) 135 @composition_module.class_eval do 136 define_method(name) do 137 if compositions.has_key?(name) 138 compositions[name] 139 elsif frozen? 140 # composer_meth is private 141 send(composer_meth) 142 else 143 compositions[name] = send(composer_meth) 144 end 145 end 146 alias_method(name, name) 147 148 meth = :"#{name}=" 149 define_method(meth) do |v| 150 modified! 151 compositions[name] = v 152 end 153 alias_method(meth, meth) 154 end 155 end
Freeze composition information when freezing model class.
# File lib/sequel/plugins/composition.rb 158 def freeze 159 compositions.freeze.each_value(&:freeze) 160 @composition_module.freeze 161 162 super 163 end