Parent

Class Index [+]

Quicksearch

DataMapper::Associations::ManyToMany::Relationship

Constants

OPTIONS

Public Instance Methods

child_key() click to toggle source

Returns a set of keys that identify the target model

@return [DataMapper::PropertySet]

  a set of properties that identify the target model

@api semipublic

    # File lib/dm-core/associations/many_to_many.rb, line 15
15:         def child_key
16:           return @child_key if defined?(@child_key)
17: 
18:           repository_name = child_repository_name || parent_repository_name
19:           properties      = child_model.properties(repository_name)
20: 
21:           @child_key = if @child_properties
22:             child_key = properties.values_at(*@child_properties)
23:             properties.class.new(child_key).freeze
24:           else
25:             properties.key
26:           end
27:         end
Also aliased as: target_key
eager_load(source, other_query = nil) click to toggle source

Eager load the collection using the source as a base

@param [Resource, Collection] source

  the source to query with

@param [Query, Hash] other_query

  optional query to restrict the collection

@return [ManyToMany::Collection]

  the loaded collection for the source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 158
158:         def eager_load(source, other_query = nil)
159:           # FIXME: enable SEL for m:m relationships
160:           source.model.all(query_for(source, other_query))
161:         end
finalize() click to toggle source

Initialize the chain for “many to many” relationships

@api public

     # File lib/dm-core/associations/many_to_many.rb, line 130
130:         def finalize
131:           through
132:           via
133:         end
query() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 141
141:         def query
142:           # TODO: consider making this a query_for method, so that ManyToMany::Relationship#query only
143:           # returns the query supplied in the definition
144:           @many_to_many_query ||= super.merge(:links => links).freeze
145:         end
source_scope(source) click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 136
136:         def source_scope(source)
137:           { through.inverse => source }
138:         end
target_key() click to toggle source

@api semipublic

Alias for: child_key
through() click to toggle source

Intermediate association for through model relationships

Example: for :bugs association in

class Software::Engineer

  include DataMapper::Resource

  has n, :missing_tests
  has n, :bugs, :through => :missing_tests

end

through is :missing_tests

TODO: document a case when through option is a model and not an association name

@api semipublic

    # File lib/dm-core/associations/many_to_many.rb, line 51
51:         def through
52:           return @through if defined?(@through)
53: 
54:           @through = options[:through]
55: 
56:           if @through.kind_of?(Associations::Relationship)
57:             return @through
58:           end
59: 
60:           model           = source_model
61:           repository_name = source_repository_name
62:           relationships   = model.relationships(repository_name)
63:           name            = through_relationship_name
64: 
65:           @through = relationships[name] ||
66:             DataMapper.repository(repository_name) do
67:               model.has(min..max, name, through_model, one_to_many_options)
68:             end
69: 
70:           @through.child_key
71: 
72:           @through
73:         end
via() click to toggle source

@api semipublic

     # File lib/dm-core/associations/many_to_many.rb, line 76
 76:         def via
 77:           return @via if defined?(@via)
 78: 
 79:           @via = options[:via]
 80: 
 81:           if @via.kind_of?(Associations::Relationship)
 82:             return @via
 83:           end
 84: 
 85:           name            = self.name
 86:           through         = self.through
 87:           repository_name = through.relative_target_repository_name
 88:           through_model   = through.target_model
 89:           relationships   = through_model.relationships(repository_name)
 90:           singular_name   = DataMapper::Inflector.singularize(name.to_s).to_sym
 91: 
 92:           @via = relationships[@via] ||
 93:             relationships[name]      ||
 94:             relationships[singular_name]
 95: 
 96:           @via ||= if anonymous_through_model?
 97:             DataMapper.repository(repository_name) do
 98:               through_model.belongs_to(singular_name, target_model, many_to_one_options)
 99:             end
100:           else
101:             raise UnknownRelationshipError, "No relationships named #{name} or #{singular_name} in #{through_model}"
102:           end
103: 
104:           @via.child_key
105: 
106:           @via
107:         end

Private Instance Methods

anonymous_through_model?() click to toggle source

Check if the :through association uses an anonymous model

An anonymous model means that DataMapper creates the model in-memory, and sets the relationships to join the source and the target model.

@return [Boolean]

  true if the through model is anonymous

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 222
222:         def anonymous_through_model?
223:           options[:through] == Resource
224:         end
collection_class() click to toggle source

Returns collection class used by this type of relationship

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 313
313:         def collection_class
314:           ManyToMany::Collection
315:         end
inverse_class() click to toggle source

Returns the inverse relationship class

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 274
274:         def inverse_class
275:           self.class
276:         end
invert() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 279
279:         def invert
280:           inverse_class.new(inverse_name, parent_model, child_model, inverted_options)
281:         end
inverted_options() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 284
284:         def inverted_options
285:           links   = self.links.dup
286:           through = links.pop.inverse
287: 
288:           links.reverse_each do |relationship|
289:             inverse = relationship.inverse
290: 
291:             through = self.class.new(
292:               inverse.name,
293:               inverse.child_model,
294:               inverse.parent_model,
295:               inverse.options.merge(:through => through)
296:             )
297:           end
298: 
299:           options = self.options
300: 
301:           DataMapper::Ext::Hash.only(options, *OPTIONS - [ :min, :max ]).update(
302:             :through    => through,
303:             :child_key  => options[:parent_key],
304:             :parent_key => options[:child_key],
305:             :inverse    => self
306:           )
307:         end
many_to_one_options() click to toggle source

@api semipublic

     # File lib/dm-core/associations/many_to_many.rb, line 261
261:           def many_to_one_options
262:             { :parent_key => target_key.map { |property| property.name } }
263:           end
nearest_relationship() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 227
227:         def nearest_relationship
228:           return @nearest_relationship if defined?(@nearest_relationship)
229: 
230:           nearest_relationship = self
231: 
232:           while nearest_relationship.respond_to?(:through)
233:             nearest_relationship = nearest_relationship.through
234:           end
235: 
236:           @nearest_relationship = nearest_relationship
237:         end
one_to_many_options() click to toggle source

@api semipublic

     # File lib/dm-core/associations/many_to_many.rb, line 266
266:           def one_to_many_options
267:             { :parent_key => source_key.map { |property| property.name } }
268:           end
property(name, type, options = {}) click to toggle source

all properties added to the anonymous through model are keys

     # File lib/dm-core/associations/many_to_many.rb, line 174
174:               def property(name, type, options = {})
175:                 options[:key] = true
176:                 options.delete(:index)
177:                 super
178:               end
through_model() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 166
166:         def through_model
167:           namespace, name = through_model_namespace_name
168: 
169:           if namespace.const_defined?(name)
170:             namespace.const_get(name)
171:           else
172:             Model.new(name, namespace) do
173:               # all properties added to the anonymous through model are keys
174:               def property(name, type, options = {})
175:                 options[:key] = true
176:                 options.delete(:index)
177:                 super
178:               end
179:             end
180:           end
181:         end
through_model_namespace_name() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 184
184:         def through_model_namespace_name
185:           target_parts = target_model.base_model.name.split('::')
186:           source_parts = source_model.base_model.name.split('::')
187: 
188:           name = [ target_parts.pop, source_parts.pop ].sort.join
189: 
190:           namespace = Object
191: 
192:           # find the common namespace between the target_model and source_model
193:           target_parts.zip(source_parts) do |target_part, source_part|
194:             break if target_part != source_part
195:             namespace = namespace.const_get(target_part)
196:           end
197: 
198:           return namespace, name
199:         end
through_relationship_name() click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 202
202:         def through_relationship_name
203:           if anonymous_through_model?
204:             namespace = through_model_namespace_name.first
205:             relationship_name = DataMapper::Inflector.underscore(through_model.name.sub(/\A#{namespace.name}::/, '')).tr('/', '_')
206:             DataMapper::Inflector.pluralize(relationship_name).to_sym
207:           else
208:             options[:through]
209:           end
210:         end
valid_source?(source) click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 250
250:         def valid_source?(source)
251:           relationship = nearest_relationship
252:           source_key   = relationship.source_key
253:           target_key   = relationship.target_key
254: 
255:           source.kind_of?(source_model) &&
256:           target_key.valid?(source_key.get(source))
257:         end
valid_target?(target) click to toggle source

@api private

     # File lib/dm-core/associations/many_to_many.rb, line 240
240:         def valid_target?(target)
241:           relationship = via
242:           source_key   = relationship.source_key
243:           target_key   = relationship.target_key
244: 
245:           target.kind_of?(target_model) &&
246:           source_key.valid?(target_key.get(target))
247:         end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.