Module: Sequel::Plugins::Composition::ClassMethods

Defined in:
lib/sequel/plugins/composition.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#compositionsObject (readonly)

A hash with composition name keys and composition reflection hash values.



70
71
72
# File 'lib/sequel/plugins/composition.rb', line 70

def compositions
  @compositions
end

Instance Method Details

#composition(name, opts = OPTS) ⇒ Object

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, String or Symbol.

:composer

A proc that is instance evaled when the composition getter method is called to create the composition.

:decomposer

A proc that is instance evaled 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]]}

Raises:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/sequel/plugins/composition.rb', line 103

def composition(name, opts=OPTS)
  opts = opts.dup
  compositions[name] = opts
  if mapping = opts[:mapping]
    keys = mapping.map{|k| k.is_a?(Array) ? k.first : k}
    if !opts[:composer]              
      late_binding_class_option(opts, name)
      klass = opts[:class]
      class_proc = proc{klass || constantize(opts[:class_name])}
      opts[:composer] = proc do
        if values = keys.map{|k| get_column_value(k)} and values.any?{|v| !v.nil?}
          class_proc.call.new(*values)
        else
          nil
        end
      end
    end
    if !opts[:decomposer]
      setter_meths = keys.map{|k| :"#{k}="}
      cov_methods = mapping.map{|k| k.is_a?(Array) ? k.last : k}
      setters = setter_meths.zip(cov_methods)
      opts[:decomposer] = proc do
        if (o = compositions[name]).nil?
          setter_meths.each{|sm| get_column_value(sm, nil)}
        else
          setters.each{|sm, cm| get_column_value(sm, o.send(cm))}
        end
      end
    end
  end
  raise(Error, "Must provide :composer and :decomposer options, or :mapping option") unless opts[:composer] && opts[:decomposer]
  define_composition_accessor(name, opts)
end

#composition_moduleObject



72
73
74
75
# File 'lib/sequel/plugins/composition.rb', line 72

def composition_module
  Sequel::Deprecation.deprecate('Sequel::Model.composition_module', 'There is no replacement')
  @composition_module
end

#composition_module=(v) ⇒ Object



76
77
78
79
# File 'lib/sequel/plugins/composition.rb', line 76

def composition_module=(v)
  Sequel::Deprecation.deprecate('Sequel::Model.composition_module=', 'There is no replacement')
  @composition_module = v
end

#define_composition_accessor(name, opts = OPTS) ⇒ Object

Define getter and setter methods for the composition object.



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/sequel/plugins/composition.rb', line 140

def define_composition_accessor(name, opts=OPTS)
  composer = opts[:composer]
  @composition_module.class_eval do
    define_method(name) do 
      if compositions.has_key?(name)
        compositions[name]
      elsif frozen?
        instance_eval(&composer)
      else
        compositions[name] = instance_eval(&composer)
      end
    end
    define_method("#{name}=") do |v|
      modified!
      compositions[name] = v
    end
  end
end

#freezeObject

Freeze composition information when freezing model class.



160
161
162
163
164
165
# File 'lib/sequel/plugins/composition.rb', line 160

def freeze
  compositions.freeze.each_value(&:freeze)
  @composition_module.freeze

  super
end