Class: FlatMap::OpenMapper::Factory
- Inherits:
-
Object
- Object
- FlatMap::OpenMapper::Factory
- Defined in:
- lib/flat_map/open_mapper/factory.rb
Overview
Mapper factory objects are used to store mounting and trait definitions and to instantiate and setup corresponding mapper objects thereafter. Factory objects are stored by mapper classes in opposite to actual mounted mappers that are stored by mapper objects themselves.
Instance Method Summary collapse
-
#create(mapper, *owner_traits) ⇒ Object
Create a new mapper object for mounting.
-
#explicit_target(mapper) ⇒ Object?
Try to use explicit target definition passed in options to fetch a target.
-
#fetch_save_order(mapper) ⇒ Symbol
Return order relative to target of the passed
mapper
in which mapper to be created should be saved. -
#fetch_target_from(mapper) ⇒ Object
Fetch the target for the mapper being created based on target of a host mapper.
-
#initialize(identifier, options = {}, &block) ⇒ Factory
constructor
Initializes factory with an identifier (name of a mounted mapper, or the actual class for a trait) and a set of options.
-
#mapper_class ⇒ Class
Return the anonymous trait class if the factory defines a trait.
-
#model_mount? ⇒ Boolean
Return
true
if mapper to me mounted isModelMapper
. -
#name ⇒ Symbol?
Return the name of the mapper being defined by the factory.
-
#new_target ⇒ Object
Return new instance of
target_class
of the mapper. -
#open_mapper_class ⇒ Class
Return descendant of
OpenMapper
class to be used when mounting open mappers. -
#open_mount? ⇒ Boolean
Return
true
if mapper to me mounted is notModelMapper
, i.e. -
#reflection_from_target(target) ⇒ ActiveRecord::Reflection::AssociationReflection?
Try to retreive an association reflection that has a name corresponding to the one of
self
. -
#required_for_any_trait?(traits) ⇒ Boolean
Return
true
if the factory is required to be able to apply a trait for the host mapper. -
#target_from_association(owner_target) ⇒ Object
Try to fetch the target for a new mapper being mounted, based on correspondence of the mounting name and presence of the association with a similar name in the host mapper.
-
#target_from_name(target) ⇒ Object
Send the name of the mounting to the target of the host mapper, and use return value as a target for a mapper being created.
-
#trait_name ⇒ Object
Return the trait name if the factory defines a trait.
-
#traited? ⇒ Boolean
Return
true
if factory defines a trait. -
#traits ⇒ Array<Symbol>
Return the list of traits that should be applied for a mapper being mounted on a host mapper.
Constructor Details
#initialize(identifier, options = {}, &block) ⇒ Factory
Initializes factory with an identifier (name of a mounted mapper, or the actual class for a trait) and a set of options. Those args are used to create actual mapper object for the host mapper.
14 15 16 |
# File 'lib/flat_map/open_mapper/factory.rb', line 14 def initialize(identifier, = {}, &block) @identifier, @options, @extension = identifier, , block end |
Instance Method Details
#create(mapper, *owner_traits) ⇒ Object
Create a new mapper object for mounting. If the factory is traited, the new mapper is a part of a host mapper, and is ‘owned’ by it. Otherwise, assign the name of the factory to it to be able to find it later on.
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/flat_map/open_mapper/factory.rb', line 207 def create(mapper, *owner_traits) save_order = @options[:save] || fetch_save_order(mapper) || :after new_one = mapper_class.new(fetch_target_from(mapper), *(traits + owner_traits).uniq, &@extension) if traited? new_one.owner = mapper else new_one.host = mapper new_one.name = @identifier new_one.save_order = save_order if (suffix = @options[:suffix] || mapper.suffix).present? new_one.suffix = suffix new_one.name = :"#{@identifier}_#{suffix}" else new_one.name = @identifier end end new_one end |
#explicit_target(mapper) ⇒ Object?
Try to use explicit target definition passed in options to fetch a target. If this value is a Proc
, will call it with owner target as argument.
120 121 122 123 124 125 126 127 128 129 |
# File 'lib/flat_map/open_mapper/factory.rb', line 120 def explicit_target(mapper) if @options.key?(:target) target = @options[:target] case target when Proc then target.call(mapper.target) when Symbol then mapper.send(target) else target end end end |
#fetch_save_order(mapper) ⇒ Symbol
Return order relative to target of the passed mapper
in which mapper to be created should be saved. In particular, targets of :belongs_to
associations should be saved before target of mapper
is saved.
192 193 194 195 196 197 198 |
# File 'lib/flat_map/open_mapper/factory.rb', line 192 def fetch_save_order(mapper) return :after unless mapper.is_a?(ModelMapper) reflection = reflection_from_target(mapper.target) return unless reflection.present? reflection.macro == :belongs_to ? :before : :after end |
#fetch_target_from(mapper) ⇒ Object
Fetch the target for the mapper being created based on target of a host mapper.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/flat_map/open_mapper/factory.rb', line 92 def fetch_target_from(mapper) owner_target = mapper.target return owner_target if traited? if open_mount? explicit_target(mapper) || new_target else explicit_target(mapper) || target_from_association(owner_target) || target_from_name(owner_target) || new_target end end |
#mapper_class ⇒ Class
Return the anonymous trait class if the factory defines a trait. Fetch and return the class of a mapper defined by a symbol.
50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/flat_map/open_mapper/factory.rb', line 50 def mapper_class @mapper_class ||= begin case when traited? then @identifier when @options[:open] then open_mapper_class when @options[:mapper_class] then @options[:mapper_class] else class_name = @options[:mapper_class_name] || "#{name.to_s.camelize}Mapper" class_name.constantize end end end |
#model_mount? ⇒ Boolean
Return true
if mapper to me mounted is ModelMapper
77 78 79 |
# File 'lib/flat_map/open_mapper/factory.rb', line 77 def model_mount? mapper_class < ModelMapper end |
#name ⇒ Symbol?
Return the name of the mapper being defined by the factory. Return nil
for the traited factory.
29 30 31 |
# File 'lib/flat_map/open_mapper/factory.rb', line 29 def name traited? ? nil : @identifier end |
#new_target ⇒ Object
Return new instance of target_class
of the mapper.
110 111 112 |
# File 'lib/flat_map/open_mapper/factory.rb', line 110 def new_target mapper_class.target_class.new end |
#open_mapper_class ⇒ Class
Return descendant of OpenMapper
class to be used when mounting open mappers.
67 68 69 70 71 72 |
# File 'lib/flat_map/open_mapper/factory.rb', line 67 def open_mapper_class klass = Class.new(OpenMapper) klass_name = "#{name.to_s.camelize}Mapper" klass.singleton_class.send(:define_method, :name){ klass_name } klass end |
#open_mount? ⇒ Boolean
Return true
if mapper to me mounted is not ModelMapper
, i.e. OpenMapper
.
84 85 86 |
# File 'lib/flat_map/open_mapper/factory.rb', line 84 def open_mount? !model_mount? end |
#reflection_from_target(target) ⇒ ActiveRecord::Reflection::AssociationReflection?
Try to retreive an association reflection that has a name corresponding to the one of self
171 172 173 174 175 176 |
# File 'lib/flat_map/open_mapper/factory.rb', line 171 def reflection_from_target(target) return unless name.present? && target.is_a?(ActiveRecord::Base) target_class = target.class reflection = target_class.reflect_on_association(name) reflection || target_class.reflect_on_association(name.to_s.pluralize.to_sym) end |
#required_for_any_trait?(traits) ⇒ Boolean
Return true
if the factory is required to be able to apply a trait for the host mapper. For example, it is required if its name is listed in traits
. It is also required if it has nested traits with names listed in traits
.
234 235 236 237 238 239 240 241 242 |
# File 'lib/flat_map/open_mapper/factory.rb', line 234 def required_for_any_trait?(traits) return true unless traited? traits.include?(trait_name) || mapper_class.mountings.any? do |factory| factory.traited? && factory.required_for_any_trait?(traits) end end |
#target_from_association(owner_target) ⇒ Object
Try to fetch the target for a new mapper being mounted, based on correspondence of the mounting name and presence of the association with a similar name in the host mapper.
For example:
class Foo < ActiveRecord::Base
has_one :baz
has_many :bars
end
class FooMapper < FlatMap::Mapper
# target of this mapper is the instance of Foo. Lets reference it as 'foo'
mount :baz # This will look for BazMapper, and will try to fetch a target for
# it based on :has_one association, i.e. foo.baz || foo.build_baz
mount :bar # This will look for BarMapper, and will try to fetch a target for
# it based on :has_many association, i.e. foo.bars.build
end
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/flat_map/open_mapper/factory.rb', line 149 def target_from_association(owner_target) return unless owner_target.is_a?(ActiveRecord::Base) reflection = reflection_from_target(owner_target) return unless reflection.present? reflection_macro = reflection.macro case when reflection_macro == :has_one && reflection.[:is_current] owner_target.send("effective_#{name}") when reflection_macro == :has_one || reflection_macro == :belongs_to owner_target.send(name) || owner_target.send("build_#{name}") when reflection_macro == :has_many owner_target.association(reflection.name).build end end |
#target_from_name(target) ⇒ Object
Send the name of the mounting to the target of the host mapper, and use return value as a target for a mapper being created.
182 183 184 |
# File 'lib/flat_map/open_mapper/factory.rb', line 182 def target_from_name(target) target.send(name) end |
#trait_name ⇒ Object
Return the trait name if the factory defines a trait.
34 35 36 |
# File 'lib/flat_map/open_mapper/factory.rb', line 34 def trait_name @options[:trait_name] if traited? end |
#traited? ⇒ Boolean
Return true
if factory defines a trait.
21 22 23 |
# File 'lib/flat_map/open_mapper/factory.rb', line 21 def traited? @identifier.is_a?(Class) end |
#traits ⇒ Array<Symbol>
Return the list of traits that should be applied for a mapper being mounted on a host mapper.
42 43 44 |
# File 'lib/flat_map/open_mapper/factory.rb', line 42 def traits Array(@options[:traits]).compact end |