Class: Mongoid::Association::Referenced::HasMany::Proxy

Inherits:
Many
  • Object
show all
Extended by:
Forwardable
Defined in:
build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb

Overview

This class defines the behavior for all associations that are a one-to-many between documents in different collections.

Since:

  • 7.0

Instance Attribute Summary

Attributes inherited from Proxy

#_association, #_base, #_target

Class Method Summary collapse

Instance Method Summary collapse

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, #init, #klass, #reset_unloaded, #substitutable

Methods included from Marshalable

#marshal_dump, #marshal_load

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.

Examples:

Create the new association.

Referenced::Many.new(base, target, association)

Parameters:

  • base (Document)

    The document this association hangs off of.

  • target (Array<Document>)

    The target of the association.

  • association (Association)

    The association metadata.

Since:

  • 2.0.0.beta.1



222
223
224
225
226
227
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 222

def initialize(base, target, association)
  enum = HasMany::Enumerable.new(target, base, association)
  init(base, enum, association) do
    raise_mixed if klass.embedded? && !klass.cyclic?
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ 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.

Parameters:

  • name (Symbol, String)

    The name of the method.

  • args (Array)

    The method args

  • block (Proc)

    Optional block to pass.

Returns:

  • (Criteria, Object)

    A Criteria or return value from the target.

Since:

  • 2.0.0.beta.1



446
447
448
449
450
451
452
453
454
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 446

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

Class Method Details

.eager_loader(association, docs) ⇒ Object

Since:

  • 7.0



567
568
569
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 567

def eager_loader(association, docs)
  Eager.new(association, docs)
end

.embedded?false

Returns true if the association is an embedded one. In this case always false.

Examples:

Is this association embedded?

Referenced::Many.embedded?

Returns:

  • (false)

    Always false.

Since:

  • 2.0.0.rc.1



580
581
582
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 580

def embedded?
  false
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.

Examples:

Append a document.

person.posts << post

Push a document.

person.posts.push(post)

Concat with other documents.

person.posts.concat([ post_one, post_two ])

Parameters:

Returns:

  • (Array<Document>)

    The loaded docs.

Since:

  • 2.0.0.beta.1



34
35
36
37
38
39
40
41
42
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 34

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) {|doc| ... } ⇒ Document Also known as: new

Build a new document from the attributes and append it to this association without saving.

Examples:

Build a new document on the association.

person.posts.build(:title => "A new post")

Parameters:

  • attributes (Hash) (defaults to: {})

    The attributes of the new document.

  • type (Class) (defaults to: nil)

    The optional subclass to build.

Yields:

  • (doc)

Returns:

Since:

  • 2.0.0.beta.1



80
81
82
83
84
85
86
87
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 80

def build(attributes = {}, type = nil)
  doc = Factory.build(type || klass, attributes)
  append(doc)
  doc.apply_post_processed_defaults
  yield(doc) if block_given?
  doc.run_callbacks(:build) { doc }
  doc
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.

Examples:

Concat with other documents.

person.posts.concat([ post_one, post_two ])

Parameters:

  • documents (Array<Document>)

    The docs to add.

Returns:

Since:

  • 2.4.0



57
58
59
60
61
62
63
64
65
66
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 57

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

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.

Examples:

Delete the document.

person.posts.delete(post)

Parameters:

  • document (Document)

    The document to remove.

Returns:

Since:

  • 2.1.0



103
104
105
106
107
108
109
110
111
112
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 103

def delete(document)
  execute_callback :before_remove, document
  _target.delete(document) do |doc|
    if doc
      unbind_one(doc)
      cascade!(doc) if !_assigning?
    end
    execute_callback :after_remove, doc
  end
end

#delete_all(conditions = nil) ⇒ Integer

Deletes all related documents from the database given the supplied conditions.

Examples:

Delete all documents in the association.

person.posts.delete_all

Conditonally delete all documents in the association.

person.posts.delete_all({ :title => "Testing" })

Parameters:

  • conditions (Hash) (defaults to: nil)

    Optional conditions to delete with.

Returns:

  • (Integer)

    The number of documents deleted.

Since:

  • 2.0.0.beta.1



128
129
130
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 128

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.

Examples:

Destroy all documents in the association.

person.posts.destroy_all

Conditonally destroy all documents in the association.

person.posts.destroy_all({ :title => "Testing" })

Parameters:

  • conditions (Hash) (defaults to: nil)

    Optional conditions to destroy with.

Returns:

  • (Integer)

    The number of documents destroyd.

Since:

  • 2.0.0.beta.1



146
147
148
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 146

def destroy_all(conditions = nil)
  remove_all(conditions, :destroy_all)
end

#eachArray<Document>

Note:

This will load the entire association into memory.

Iterate over each document in the association and yield to the provided block.

Examples:

Iterate over the documents.

person.posts.each do |post|
  post.save
end

Returns:

  • (Array<Document>)

    The loaded docs.

Since:

  • 2.1.0



163
164
165
166
167
168
169
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 163

def each
  if block_given?
    _target.each { |doc| yield(doc) }
  else
    to_enum
  end
end

#exists?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.

Examples:

Are there persisted documents?

person.posts.exists?

Returns:

  • (true, false)

    True is persisted documents exist, false if not.

Since:

  • 7.0



184
185
186
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 184

def exists?
  criteria.exists?
end

#find(*args) ⇒ Document, Criteria

Note:

This will keep matching documents in memory for iteration later.

Find the matchind document on the association, either based on id or conditions.

Examples:

Find by an id.

person.posts.find(BSON::ObjectId.new)

Find by multiple ids.

person.posts.find([ BSON::ObjectId.new, BSON::ObjectId.new ])

Parameters:

Returns:

Since:

  • 2.0.0.beta.1



205
206
207
208
209
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 205

def find(*args)
  matching = criteria.find(*args)
  Array(matching).each { |doc| _target.push(doc) }
  matching
end

#nullifyObject 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.

Examples:

Nullify the association.

person.posts.nullify

Since:

  • 2.0.0.rc.1



237
238
239
240
241
242
243
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 237

def nullify
  criteria.update_all(foreign_key => nil)
  _target.clear do |doc|
    unbind_one(doc)
    doc.changed_attributes.delete(foreign_key)
  end
end

#purgeMany Also known as: clear

Clear the association. Will delete the documents from the db if they are already persisted.

Examples:

Clear the association.

person.posts.clear

Returns:

  • (Many)

    The association emptied.

Since:

  • 2.0.0.beta.1



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 256

def purge
  unless _association.destructive?
    nullify
  else
    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 => e
        after_remove_error = e
      end
    end
    raise after_remove_error if after_remove_error
    many
  end
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.

Examples:

Replace the association.

person.posts.substitute([ new_post ])

Parameters:

  • replacement (Array<Document>)

    The replacement target.

Returns:

  • (Many)

    The association.

Since:

  • 2.0.0.rc.1



291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 291

def substitute(replacement)
  if replacement
    new_docs, docs = replacement.compact, []
    new_ids = new_docs.map { |doc| doc._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

#unscopedCriteria

Get a criteria for the documents without the default scoping applied.

Examples:

Get the unscoped criteria.

person.posts.unscoped

Returns:

Since:

  • 2.4.0



315
316
317
# File 'build/mongoid-master/lib/mongoid/association/referenced/has_many/proxy.rb', line 315

def unscoped
  klass.unscoped.where(foreign_key => _base.send(_association.primary_key))
end