Class: Mongoid::Association::Referenced::HasMany::Proxy
- Extended by:
- Forwardable, ClassMethods
- Defined in:
- lib/mongoid/association/referenced/has_many/proxy.rb
Overview
Transparent proxy for has_many associations. An instance of this class is returned when calling the association getter method on the subject document. This class inherits from Mongoid::Association::Proxy and forwards most of its methods to the target of the association, i.e. the array of documents on the opposite-side collection which must be loaded.
Direct Known Subclasses
Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy
Defined Under Namespace
Modules: ClassMethods
Constant Summary
Constants inherited from Proxy
Instance Attribute Summary
Attributes inherited from Proxy
#_association, #_base, #_target
Instance Method Summary collapse
-
#<<(*args) ⇒ Array<Document>
(also: #push)
Appends a document or array of documents to the association.
-
#build(attributes = {}, type = nil) ⇒ Document
(also: #new)
Build a new document from the attributes and append it to this association without saving.
-
#concat(documents) ⇒ Array<Document>
Appends an array of documents to the association.
-
#delete(document) ⇒ Document
(also: #delete_one)
Delete the document from the association.
-
#delete_all(conditions = nil) ⇒ Integer
Deletes all related documents from the database given the supplied conditions.
-
#destroy_all(conditions = nil) ⇒ Integer
Destroys all related documents from the database given the supplied conditions.
-
#each(&block) ⇒ Array<Document>
Iterate over each document in the association and yield to the provided block.
-
#exists?(id_or_conditions = :none) ⇒ true | false
Determine if any documents in this association exist in the database.
-
#find(*args) {|Object| ... } ⇒ Document | Array<Document> | nil
Find the matching document on the association, either based on id or conditions.
-
#initialize(base, target, association) ⇒ Proxy
constructor
Instantiate a new references_many association.
-
#nullify ⇒ Object
(also: #nullify_all)
Removes all associations between the base document and the target documents by deleting the foreign keys and the references, orphaning the target documents in the process.
-
#purge ⇒ Many
(also: #clear)
Clear the association.
-
#substitute(replacement) ⇒ Many
Substitutes the supplied target documents for the existing documents in the association.
-
#unscoped ⇒ Criteria
Get a criteria for the documents without the default scoping applied.
Methods included from ClassMethods
Methods inherited from Many
#blank?, #create, #create!, #find_or_create_by, #find_or_create_by!, #find_or_initialize_by, #nil?, #respond_to?, #scoped, #serializable_hash
Methods inherited from Proxy
apply_ordering, #extend_proxies, #klass, #reset_unloaded, #substitutable
Methods included from Marshalable
Constructor Details
#initialize(base, target, association) ⇒ Proxy
Instantiate a new references_many association. Will set the foreign key and the base on the inverse object.
48 49 50 51 52 53 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 48 def initialize(base, target, association) enum = HasMany::Enumerable.new(target, base, association) super(base, enum, association) do raise_mixed if klass. && !klass.cyclic? end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing ⇒ Criteria | Object (private)
If the target array does not respond to the supplied method then try to find a named scope or criteria on the class and send the call there.
If the method exists on the array, use the default proxy behavior.
TODO: make sure we are consistingly using respond_to_missing
anywhere we define method_missing.
rubocop:disable Style/MissingRespondToMissing
465 466 467 468 469 470 471 472 473 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 465 ruby2_keywords def method_missing(name, *args, &block) if _target.respond_to?(name) _target.send(name, *args, &block) else klass.send(:with_scope, criteria) do criteria.public_send(name, *args, &block) end end end |
Instance Method Details
#<<(*args) ⇒ Array<Document> Also known as: push
Appends a document or array of documents to the association. Will set the parent and update the index in the process.
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 70 def <<(*args) docs = args.flatten return concat(docs) if docs.size > 1 if (doc = docs.first) append(doc) doc.save if persistable? && !_assigning? && !doc.validated? end self end |
#build(attributes = {}, type = nil) ⇒ Document Also known as: new
Build a new document from the attributes and append it to this association without saving.
115 116 117 118 119 120 121 122 123 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 115 def build(attributes = {}, type = nil) Factory.execute_build(type || klass, attributes, execute_callbacks: false).tap do |doc| append(doc) doc.apply_post_processed_defaults yield doc if block_given? doc.run_pending_callbacks doc.run_callbacks(:build) { doc } end end |
#concat(documents) ⇒ Array<Document>
Appends an array of documents to the association. Performs a batch insert of the documents instead of persisting one at a time.
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 92 def concat(documents) docs, inserts = [], [] documents.each do |doc| next unless doc append(doc) save_or_delay(doc, docs, inserts) if persistable? end persist_delayed(docs, inserts) self end |
#delete(document) ⇒ Document Also known as: delete_one
Delete the document from the association. This will set the foreign key on the document to nil. If the dependent options on the association are :delete_all or :destroy the appropriate removal will occur.
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 137 def delete(document) execute_callbacks_around(:remove, document) do result = _target.delete(document) do |doc| if doc unbind_one(doc) cascade!(doc) unless _assigning? end end result.tap { reset_unloaded } end end |
#delete_all(conditions = nil) ⇒ Integer
Deletes all related documents from the database given the supplied conditions.
166 167 168 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 166 def delete_all(conditions = nil) remove_all(conditions, :delete_all) end |
#destroy_all(conditions = nil) ⇒ Integer
Destroys all related documents from the database given the supplied conditions.
182 183 184 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 182 def destroy_all(conditions = nil) remove_all(conditions, :destroy_all) end |
#each(&block) ⇒ Array<Document>
This will load the entire association into memory.
Iterate over each document in the association and yield to the provided block.
197 198 199 200 201 202 203 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 197 def each(&block) if block _target.each(&block) else to_enum end end |
#exists?(id_or_conditions = :none) ⇒ true | false
Determine if any documents in this association exist in the database.
If the association contains documents but all of the documents exist only in the application, i.e. have not been persisted to the database, this method returns false.
This method queries the database on each invocation even if the association is already loaded into memory.
227 228 229 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 227 def exists?(id_or_conditions = :none) criteria.exists?(id_or_conditions) end |
#find(*args) {|Object| ... } ⇒ Document | Array<Document> | nil
Each argument can be an individual id, an array of ids or a nested array. Each array will be flattened.
This will keep matching documents in memory for iteration later.
Find the matching document on the association, either based on id or conditions.
This method delegates to Mongoid::Criteria#find. If this method is not given a block, it returns one or many documents for the provided _id values.
If this method is given a block, it returns the first document of those found by the current Criteria object for which the block returns a truthy value.
262 263 264 265 266 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 262 def find(*args, &block) matching = criteria.find(*args, &block) Array(matching).each { |doc| _target.push(doc) } matching end |
#nullify ⇒ Object Also known as: nullify_all
Removes all associations between the base document and the target documents by deleting the foreign keys and the references, orphaning the target documents in the process.
274 275 276 277 278 279 280 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 274 def nullify criteria.update_all(foreign_key => nil) _target.clear do |doc| unbind_one(doc) doc.changed_attributes.delete(foreign_key) end end |
#purge ⇒ Many Also known as: clear
Clear the association. Will delete the documents from the db if they are already persisted.
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 291 def purge return nullify unless _association.destructive? after_remove_error = nil criteria.delete_all many = _target.clear do |doc| execute_callback :before_remove, doc unbind_one(doc) doc.destroyed = true begin execute_callback :after_remove, doc rescue StandardError => e after_remove_error = e end end raise after_remove_error if after_remove_error many end |
#substitute(replacement) ⇒ Many
Substitutes the supplied target documents for the existing documents in the association. If the new target is nil, perform the necessary deletion.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 324 def substitute(replacement) if replacement new_docs, docs = replacement.compact, [] new_ids = new_docs.map(&:_id) remove_not_in(new_ids) new_docs.each do |doc| docs.push(doc) if doc.send(foreign_key) != _base.send(_association.primary_key) end concat(docs) else purge end self end |
#unscoped ⇒ Criteria
Get a criteria for the documents without the default scoping applied.
346 347 348 |
# File 'lib/mongoid/association/referenced/has_many/proxy.rb', line 346 def unscoped klass.unscoped.where(foreign_key => _base.send(_association.primary_key)) end |