Class: FlatMap::BaseMapper::Factory
- Inherits:
-
Object
- Object
- FlatMap::BaseMapper::Factory
- Defined in:
- lib/flat_map/base_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(owner_target) ⇒ Object?
Try to use explicit target definition passed in options to fetch a target.
-
#explicit_target!(mapper) ⇒ Object
When creating mappers mounted on top of EmptyMapper, target cannot be implicitly fetched from it and should be specified explicitly.
-
#fetch_save_order(mapper) ⇒ Symbol
Return order relative to target of the passed
mapperin 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.
-
#name ⇒ Symbol?
Return the name of the mapper being defined by the factory.
-
#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
trueif 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.
-
#targeted_mount? ⇒ Boolean
Return
trueif factory should create targeted mapper. -
#trait_name ⇒ Object
Return the trait name if the factory defines a trait.
-
#traited? ⇒ Boolean
Return
trueif 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/base_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.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/flat_map/base_mapper/factory.rb', line 193 def create(mapper, *owner_traits) save_order = @options[:save] || fetch_save_order(mapper) || :after all_traits = (traits + owner_traits).uniq new_one = if targeted_mount? then mapper_class.new(fetch_target_from(mapper), *all_traits, &@extension) else mapper_class.new(*all_traits, &@extension) end 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(owner_target) ⇒ 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.
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/flat_map/base_mapper/factory.rb', line 105 def explicit_target(owner_target) if @options.key?(:target) target = @options[:target] if target.is_a? Proc target.call(owner_target) else target end end end |
#explicit_target!(mapper) ⇒ Object
When creating mappers mounted on top of EmptyMapper, target cannot be implicitly fetched from it and should be specified explicitly.
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/flat_map/base_mapper/factory.rb', line 85 def explicit_target!(mapper) target = @options[:target] if target.present? case target when Proc then target.call when Symbol then mapper.send(target) else target end else raise Mapper::Targeting::NoTargetError.new(mapper_class) 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.
178 179 180 181 182 183 184 |
# File 'lib/flat_map/base_mapper/factory.rb', line 178 def fetch_save_order(mapper) return :after if mapper.is_a?(EmptyMapper) 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.
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/flat_map/base_mapper/factory.rb', line 68 def fetch_target_from(mapper) return explicit_target!(mapper) if mapper.is_a?(EmptyMapper) && targeted_mount? owner_target = mapper.target return owner_target if traited? explicit_target(owner_target) || target_from_association(owner_target) || target_from_name(owner_target) 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 |
# File 'lib/flat_map/base_mapper/factory.rb', line 50 def mapper_class return @identifier if traited? class_name = @options[:mapper_class_name] || "#{name.to_s.camelize}Mapper" class_name.constantize 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/base_mapper/factory.rb', line 29 def name traited? ? nil : @identifier end |
#reflection_from_target(target) ⇒ ActiveRecord::Reflection::AssociationReflection?
Try to retreive an association reflection that has a name corresponding to the one of self
157 158 159 160 161 162 |
# File 'lib/flat_map/base_mapper/factory.rb', line 157 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.
228 229 230 231 232 233 234 235 236 |
# File 'lib/flat_map/base_mapper/factory.rb', line 228 def required_for_any_trait?(traits) return true unless traited? traits.include?(trait_name) || mapper_class.mountings.any?{ |factory| factory.traited? && factory.required_for_any_trait?(traits) } 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
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/flat_map/base_mapper/factory.rb', line 134 def target_from_association(owner_target) return unless owner_target.kind_of?(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 else # nil 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.
168 169 170 |
# File 'lib/flat_map/base_mapper/factory.rb', line 168 def target_from_name(target) target.send(name) end |
#targeted_mount? ⇒ Boolean
Return true if factory should create targeted mapper.
60 61 62 |
# File 'lib/flat_map/base_mapper/factory.rb', line 60 def targeted_mount? mapper_class < Mapper end |
#trait_name ⇒ Object
Return the trait name if the factory defines a trait.
34 35 36 |
# File 'lib/flat_map/base_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/base_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/base_mapper/factory.rb', line 42 def traits Array(@options[:traits]).compact end |