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.
387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/mongoid/association/accessors.rb', line 387 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.
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/mongoid/association/accessors.rb', line 412 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 |
# 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) value = send("build_#{name}") if value.nil? && association.autobuilding? && !without_autobuild? 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.
319 320 321 322 323 324 325 326 |
# File 'lib/mongoid/association/accessors.rb', line 319 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.
368 369 370 371 372 373 374 375 376 |
# File 'lib/mongoid/association/accessors.rb', line 368 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.
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
# File 'lib/mongoid/association/accessors.rb', line 339 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 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 |