class Mongoid::Relations::Referenced::ManyToMany

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

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_to_many.rb, line 26
def <<(*args)
  docs = args.flatten
  return concat(docs) if docs.size > 1
  if doc = docs.first
    append(doc)
    base.add_to_set(foreign_key, doc.id)
    if child_persistable?(doc)
      doc.save
    end
  end
  unsynced(base, foreign_key) and 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 [ Hash ] options The scoped assignment options.
@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_to_many.rb, line 92
def build(attributes = {}, options = {}, type = nil)
  if options.is_a? Class
    options, type = {}, options
  end

  doc = Factory.build(type || klass, attributes, options)
  base.send(foreign_key).push(doc.id)
  append(doc)
  doc.apply_post_processed_defaults
  unsynced(doc, inverse_foreign_key)
  yield(doc) if block_given?
  doc
end
Also aliased as: new
clear() click to toggle source
Alias for: nullify
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_to_many.rb, line 51
def concat(documents)
  ids, docs, inserts = {}, [], []
  documents.each do |doc|
    next unless doc
    append(doc)
    if persistable? || _creating?
      ids[doc.id] = true
      save_or_delay(doc, docs, inserts)
    else
      existing = base.send(foreign_key)
      unless existing.include?(doc.id)
        existing.push(doc.id) and unsynced(base, foreign_key)
      end
    end
  end
  if persistable? || _creating?
    base.push_all(foreign_key, ids.keys)
  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_to_many.rb, line 119
def delete(document)
  doc = super
  if doc && persistable?
    base.pull(foreign_key, doc.id)
    target._unloaded = criteria
    unsynced(base, foreign_key)
  end
  doc
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.preferences.nullify

@since 2.0.0.rc.1

# File lib/mongoid/relations/referenced/many_to_many.rb, line 137
def nullify
  target.each do |doc|
    execute_callback :before_remove, doc
  end
  unless metadata.forced_nil_inverse?
    criteria.pull(inverse_foreign_key, base.id)
  end
  if persistable?
    base.set(
      foreign_key,
      base.send(foreign_key).clear
    )
  end
  after_remove_error = nil
  many_to_many = target.clear do |doc|
    unbind_one(doc)
    unless metadata.forced_nil_inverse?
      doc.changed_attributes.delete(inverse_foreign_key)
    end
    begin
      execute_callback :after_remove, doc
    rescue => e
      after_remove_error = e
    end
  end
  raise after_remove_error if after_remove_error
  many_to_many
end
Also aliased as: nullify_all, clear, purge
nullify_all() click to toggle source
Alias for: nullify
purge() click to toggle source
Alias for: nullify
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.preferences.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_to_many.rb, line 181
def substitute(replacement)
  purge
  unless replacement.blank?
    push(replacement.compact.uniq)
  else
    reset_unloaded
  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.preferences.unscoped

@return [ Criteria ] The unscoped criteria.

@since 2.4.0

# File lib/mongoid/relations/referenced/many_to_many.rb, line 200
def unscoped
  klass.unscoped.any_in(_id: base.send(foreign_key))
end