class Mongoid::Relations::Referenced::Many

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

Public Class Methods

new(base, target, metadata) click to toggle source

Instantiate a new references_many relation. Will set the foreign key and the base on the inverse object.

@example Create the new relation.

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

@param [ Document ] base The document this relation hangs off of. @param [ Array<Document> ] target The target of the relation. @param [ Metadata ] metadata The relation's metadata.

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 218
def initialize(base, target, metadata)
  init(base, Targets::Enumerable.new(target), metadata) do
    raise_mixed if klass.embedded? && !klass.cyclic?
  end
end

Public Instance Methods

<<(*args) click to toggle source

Appends a document or array of documents to the relation. Will set the parent and update the index in the process.

@example Append a document.

person.posts << post

@example Push a document.

person.posts.push(post)

@example Concat with other documents.

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

@param [ Document, Array<Document> ] *args Any number of documents.

@return [ Array<Document> ] The loaded docs.

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 29
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
Also aliased as: push
build(attributes = {}, options = {}, type = nil) { |doc| ... } click to toggle source

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

@example Build a new document on the relation.

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

@overload build(attributes = {}, options = {}, type = nil)

@param [ Hash ] attributes The attributes of the new document.
@param [ Hash ] options The scoped assignment options.
@param [ Class ] type The optional subclass to build.

@overload build(attributes = {}, type = nil)

@param [ Hash ] attributes The attributes of the new document.
@param [ Class ] type The optional subclass to build.

@return [ Document ] The new document.

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 80
def build(attributes = {}, options = {}, type = nil)
  if options.is_a? Class
    options, type = {}, options
  end

  doc = Factory.build(type || klass, attributes, options)
  append(doc)
  doc.apply_post_processed_defaults
  yield(doc) if block_given?
  doc.run_callbacks(:build) { doc }
  doc
end
Also aliased as: new
clear() click to toggle source
Alias for: purge
concat(documents) click to toggle source

Appends an array of documents to the relation. Performs a batch insert of the documents instead of persisting one at a time.

@example Concat with other documents.

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

@param [ Array<Document> ] documents The docs to add.

@return [ Array<Document> ] The documents.

@since 2.4.0

# File lib/mongoid/relations/referenced/many.rb, line 51
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) click to toggle source

Delete the document from the relation. This will set the foreign key on the document to nil. If the dependent options on the relation are :delete or :destroy the appropriate removal will occur.

@example Delete the document.

person.posts.delete(post)

@param [ Document ] document The document to remove.

@return [ Document ] The matching document.

@since 2.1.0

# File lib/mongoid/relations/referenced/many.rb, line 106
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) click to toggle source

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

@example Delete all documents in the relation.

person.posts.delete_all

@example Conditonally delete all documents in the relation.

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

@param [ Hash ] conditions Optional conditions to delete with.

@return [ Integer ] The number of documents deleted.

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 131
def delete_all(conditions = nil)
  remove_all(conditions, :delete_all)
end
destroy_all(conditions = nil) click to toggle source

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

@example Destroy all documents in the relation.

person.posts.destroy_all

@example Conditonally destroy all documents in the relation.

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

@param [ Hash ] conditions Optional conditions to destroy with.

@return [ Integer ] The number of documents destroyd.

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 149
def destroy_all(conditions = nil)
  remove_all(conditions, :destroy_all)
end
each() { |doc| ... } click to toggle source

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

@note This will load the entire relation into memory.

@example Iterate over the documents.

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

@return [ Array<Document> ] The loaded docs.

@since 2.1.0

# File lib/mongoid/relations/referenced/many.rb, line 166
def each
  if block_given?
    target.each { |doc| yield(doc) }
  else
    to_enum
  end
end
exists?() click to toggle source

Determine if any documents in this relation exist in the database.

@example Are there persisted documents?

person.posts.exists?

@return [ true, false ] True is persisted documents exist, false if not.

# File lib/mongoid/relations/referenced/many.rb, line 180
def exists?
  criteria.exists?
end
find(*args) click to toggle source

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

@example Find by an id.

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

@example Find by multiple ids.

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

@note This will keep matching documents in memory for iteration

later.

@param [ Moped::BSON::ObjectId, Array<Moped::BSON::ObjectId> ] arg The ids.

@return [ Document, Criteria ] The matching document(s).

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 201
def find(*args)
  matching = criteria.find(*args)
  Array(matching).each { |doc| target.push(doc) }
  matching
end
new(attributes = {}, options = {}, type = nil) click to toggle source
Alias for: build
nullify() click to toggle source

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.

@example Nullify the relation.

person.posts.nullify

@since 2.0.0.rc.1

# File lib/mongoid/relations/referenced/many.rb, line 232
def nullify
  criteria.update_all(foreign_key => nil)
  target.clear do |doc|
    unbind_one(doc)
    doc.changed_attributes.delete(foreign_key)
  end
end
Also aliased as: nullify_all
nullify_all() click to toggle source
Alias for: nullify
purge() click to toggle source

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

@example Clear the relation.

person.posts.clear

@return [ Many ] The relation emptied.

@since 2.0.0.beta.1

# File lib/mongoid/relations/referenced/many.rb, line 250
def purge
  unless metadata.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
Also aliased as: clear
push(*args) click to toggle source
Alias for: <<
substitute(replacement) click to toggle source

Substitutes the supplied target documents for the existing documents in the relation. If the new target is nil, perform the necessary deletion.

@example Replace the relation.

person.posts.substitute([ new_post ])

@param [ Array<Document> ] replacement The replacement target.

@return [ Many ] The relation.

@since 2.0.0.rc.1

# File lib/mongoid/relations/referenced/many.rb, line 284
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.id
    end
    concat(docs)
  else
    purge
  end
  self
end
unscoped() click to toggle source

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

@example Get the unscoped criteria.

person.posts.unscoped

@return [ Criteria ] The unscoped criteria.

@since 2.4.0

# File lib/mongoid/relations/referenced/many.rb, line 308
def unscoped
  klass.unscoped.where(
    foreign_key => Conversions.flag(base.id, metadata)
  )
end