Module: Mongoid::Association::Accessors
- Extended by:
- ActiveSupport::Concern
- Included in:
- Mongoid::Association
- Defined in:
- lib/mongoid/association/accessors.rb
Overview
This module contains all the behavior related to accessing associations through the getters and setters, and how to delegate to builders to create new ones.
Class Method Summary collapse
-
.define_builder!(association) ⇒ Class
Defines a builder method for an embeds_one association.
-
.define_creator!(association) ⇒ Class
Defines a creator method for an embeds_one association.
-
.define_existence_check!(association) ⇒ Class
Adds the existence check for associations.
-
.define_getter!(association) ⇒ Class
Defines the getter for the association.
-
.define_ids_getter!(association) ⇒ Class
Defines the getter for the ids of documents in the association.
-
.define_ids_setter!(association) ⇒ Object
Defines the setter method that allows you to set documents in this association by their ids.
-
.define_setter!(association) ⇒ Class
Defines the setter for the association.
Instance Method Summary collapse
-
#__build__(name, object, association, selected_fields = nil) ⇒ Proxy
Builds the related document and creates the association unless the document is nil, then sets the association on this document.
-
#create_relation(object, association, selected_fields = nil) ⇒ Proxy
Create an association from an object and association metadata.
-
#reset_relation_criteria(name) ⇒ Object
Resets the criteria inside the association proxy.
-
#set_relation(name, relation) ⇒ Proxy
Set the supplied association to an instance variable on the class with the provided name.
Class Method Details
.define_builder!(association) ⇒ Class
Defines a builder method for an embeds_one association. This is defined as #build_name.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
# File 'lib/mongoid/association/accessors.rb', line 395 def self.define_builder!(association) name = association.name association.inverse_class.tap do |klass| klass.re_define_method("build_#{name}") do |*args| attributes, = parse_args(*args) document = Factory.build(association.relation_class, attributes) _building do child = send("#{name}=", document) child.run_callbacks(:build) child end end end end |
.define_creator!(association) ⇒ Class
Defines a creator method for an embeds_one association. This is defined as #create_name. After the object is built it will immediately save.
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/mongoid/association/accessors.rb', line 420 def self.define_creator!(association) name = association.name association.inverse_class.tap do |klass| klass.re_define_method("create_#{name}") do |*args| attributes, = parse_args(*args) document = Factory.build(association.klass, attributes) doc = _assigning do send("#{name}=", document) end doc.save save if new_record? && association.stores_foreign_key? doc end end end |
.define_existence_check!(association) ⇒ Class
Adds the existence check for associations.
277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/mongoid/association/accessors.rb', line 277 def self.define_existence_check!(association) name = association.name association.inverse_class.tap do |klass| klass.module_eval <<-END, __FILE__, __LINE__ + 1 def #{name}? without_autobuild { !__send__(:#{name}).blank? } end alias :has_#{name}? :#{name}? END end end |
.define_getter!(association) ⇒ Class
Defines the getter for the association. Nothing too special here: just return the instance variable for the association if it exists or build the thing.
299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/mongoid/association/accessors.rb', line 299 def self.define_getter!(association) name = association.name association.inverse_class.tap do |klass| klass.re_define_method(name) do |reload = false| value = get_relation(name, association, nil, reload) next value unless value.nil? && !without_autobuild? next association.fallback if association.fallback? next send("build_#{name}") if association.autobuilding? value end end end |
.define_ids_getter!(association) ⇒ Class
Defines the getter for the ids of documents in the association. Should be specify only for referenced many associations.
322 323 324 325 326 327 328 329 |
# File 'lib/mongoid/association/accessors.rb', line 322 def self.define_ids_getter!(association) ids_method = "#{association.name.to_s.singularize}_ids" association.inverse_class.tap do |klass| klass.re_define_method(ids_method) do send(association.name).pluck(:_id) end end end |
.define_ids_setter!(association) ⇒ Object
Defines the setter method that allows you to set documents in this association by their ids. The defined setter, finds documents with given ids and invokes regular association setter with found documents. Ids setters should be defined only for referenced many associations.
@param [ Mongoid::Association::Relatable ] association The association for the association.
@return [ Class ] The class being set up.
376 377 378 379 380 381 382 383 384 |
# File 'lib/mongoid/association/accessors.rb', line 376 def self.define_ids_setter!(association) ids_method = "#{association.name.to_s.singularize}_ids=" association.inverse_class.aliased_associations[ids_method.chop] = association.name.to_s association.inverse_class.tap do |klass| klass.re_define_method(ids_method) do |ids| send(association.setter, association.relation_class.find(ids.reject(&:blank?))) end end end |
.define_setter!(association) ⇒ Class
Defines the setter for the association. This does a few things based on some conditions. If there is an existing association, a target substitution will take place, otherwise a new association will be created with the supplied target.
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/mongoid/association/accessors.rb', line 342 def self.define_setter!(association) name = association.name association.inverse_class.tap do |klass| klass.re_define_method("#{name}=") do |object| without_autobuild do if association.fallback? klass = association.polymorphic? ? Mongoid::Document : association.relation_class object = nil unless object.is_a?(klass) end if value = get_relation(name, association, object) value = __build__(name, value, association) unless value.respond_to?(:substitute) set_relation(name, value.substitute(object.substitutable)) else __build__(name, object.substitutable, association) end end end end end |
Instance Method Details
#__build__(name, object, association, selected_fields = nil) ⇒ Proxy
Builds the related document and creates the association unless the document is nil, then sets the association on this document.
25 26 27 28 |
# File 'lib/mongoid/association/accessors.rb', line 25 def __build__(name, object, association, selected_fields = nil) relation = create_relation(object, association, selected_fields) set_relation(name, relation) end |
#create_relation(object, association, selected_fields = nil) ⇒ Proxy
Create an association from an object and association metadata.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/mongoid/association/accessors.rb', line 42 def create_relation(object, association, selected_fields = nil) key = @attributes[association.inverse_type] type = key ? association.resolver.model_for(key) : nil target = if t = association.build(self, object, type, selected_fields) association.create_relation(self, t) end # Only need to do this on embedded associations. The pending callbacks # are only added when materializing the documents, which only happens # on embedded associations. There is no call to the database in the # construction of a referenced association. if association. Array(target).each do |doc| doc.try(:run_pending_callbacks) end end target end |
#reset_relation_criteria(name) ⇒ Object
Resets the criteria inside the association proxy. Used by many-to-many associations to keep the underlying ids array in sync.
69 70 71 72 73 |
# File 'lib/mongoid/association/accessors.rb', line 69 def reset_relation_criteria(name) return unless instance_variable_defined?("@_#{name}") send(name).reset_unloaded end |
#set_relation(name, relation) ⇒ Proxy
Set the supplied association to an instance variable on the class with the provided name. Used as a helper just for code cleanliness.
85 86 87 |
# File 'lib/mongoid/association/accessors.rb', line 85 def set_relation(name, relation) instance_variable_set("@_#{name}", relation) end |