class Mongoid::Relations::Embedded::Many

This class handles the behaviour for a document that embeds many other documents within in it as an array.

Public Class Methods

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

Instantiate a new embeds_many relation.

@example Create the new relation.

Many.new(person, addresses, metadata)

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

@return [ Many ] The proxy.

# File lib/mongoid/relations/embedded/many.rb, line 232
def initialize(base, target, metadata)
  init(base, target, metadata) do
    target.each_with_index do |doc, index|
      integrate(doc)
      doc._index = index
    end
    @_unscoped = target.dup
    @target = scope(target)
  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.addresses << address

@example Push a document.

person.addresses.push(address)

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

# File lib/mongoid/relations/embedded/many.rb, line 22
def <<(*args)
  docs = args.flatten
  return concat(docs) if docs.size > 1
  if doc = docs.first
    append(doc)
    doc.save if persistable? && !_assigning?
  end
  self
end
Also aliased as: push
as_document() click to toggle source

Get this relation as as its representation in the database.

@example Convert the relation to an attributes hash.

person.addresses.as_document

@return [ Array<Hash> ] The relation as stored in the db.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 41
def as_document
  attributes = []
  _unscoped.each do |doc|
    attributes.push(doc.as_document)
  end
  attributes
end
build(attributes = {}, type = nil) { |doc| ... } click to toggle source

Builds a new document in the relation and appends it to the target. Takes an optional type if you want to specify a subclass.

@example Build a new document on the relation.

person.people.build(:name => "Bozo")

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

@param [ Hash ] attributes The attributes to build the document with.
@param [ Class ] type Optional class to build the document with.

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

@param [ Hash ] attributes The attributes to build the document with.
@param [ Class ] type Optional class to build the document with.

@return [ Document ] The new document.

# File lib/mongoid/relations/embedded/many.rb, line 80
def build(attributes = {}, type = nil)
  doc = Factory.build(type || __metadata.klass, attributes)
  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

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

@example Clear the relation.

person.addresses.clear

@return [ Many ] The empty relation.

# File lib/mongoid/relations/embedded/many.rb, line 97
def clear
  batch_clear(target.dup)
  self
end
concat(docs) 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.addresses.concat([ address_one, address_two ])

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

@return [ Array<Document> ] The documents.

@since 2.4.0

# File lib/mongoid/relations/embedded/many.rb, line 60
def concat(docs)
  batch_insert(docs) unless docs.empty?
  self
end
count() click to toggle source

Returns a count of the number of documents in the association that have actually been persisted to the database.

Use size if you want the total number of documents.

@example Get the count of persisted documents.

person.addresses.count

@return [ Integer ] The total number of persisted embedded docs, as

flagged by the #persisted? method.
# File lib/mongoid/relations/embedded/many.rb, line 112
def count
  target.select { |doc| doc.persisted? }.size
end
delete(document) click to toggle source

Delete the supplied document from the target. This method is proxied in order to reindex the array after the operation occurs.

@example Delete the document from the relation.

person.addresses.delete(address)

@param [ Document ] document The document to be deleted.

@return [ Document, nil ] The deleted document or nil if nothing deleted.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 127
def delete(document)
  execute_callback :before_remove, document
  doc = target.delete_one(document)
  if doc && !_binding?
    _unscoped.delete_one(doc)
    if _assigning?
      base.add_atomic_pull(doc)
    else
      doc.delete(suppress: true)
      unbind_one(doc)
    end
  end
  reindex
  execute_callback :after_remove, document
  doc
end
delete_all(conditions = {}) click to toggle source

Delete all the documents in the association without running callbacks.

@example Delete all documents from the relation.

person.addresses.delete_all

@example Conditionally delete documents from the relation.

person.addresses.delete_all({ :street => "Bond" })

@param [ Hash ] conditions Conditions on which documents to delete.

@return [ Integer ] The number of documents deleted.

# File lib/mongoid/relations/embedded/many.rb, line 155
def delete_all(conditions = {})
  remove_all(conditions, :delete)
end
delete_if() { |doc| ... } click to toggle source

Delete all the documents for which the provided block returns true.

@example Delete the matching documents.

person.addresses.delete_if do |doc|
  doc.state = "GA"
end

@return [ Many, Enumerator ] The relation or an enumerator if no

block was provided.

@since 3.1.0

Calls superclass method
# File lib/mongoid/relations/embedded/many.rb, line 170
def delete_if
  if block_given?
    target.each do |doc|
      delete(doc) if yield(doc)
    end
    self
  else
    super
  end
end
destroy_all(conditions = {}) click to toggle source

Destroy all the documents in the association whilst running callbacks.

@example Destroy all documents from the relation.

person.addresses.destroy_all

@example Conditionally destroy documents from the relation.

person.addresses.destroy_all({ :street => "Bond" })

@param [ Hash ] conditions Conditions on which documents to destroy.

@return [ Integer ] The number of documents destroyed.

# File lib/mongoid/relations/embedded/many.rb, line 192
def destroy_all(conditions = {})
  remove_all(conditions, :destroy)
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/embedded/many.rb, line 202
def exists?
  count > 0
end
find(*args) click to toggle source

Finds a document in this association through several different methods.

@example Find a document by its id.

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

@example Find documents for multiple ids.

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

@param [ Array<Object> ] args Various arguments.

@return [ Array<Document>, Document ] A single or multiple documents.

# File lib/mongoid/relations/embedded/many.rb, line 218
def find(*args)
  criteria.find(*args)
end
in_memory() click to toggle source

Get all the documents in the relation that are loaded into memory.

@example Get the in memory documents.

relation.in_memory

@return [ Array<Document> ] The documents in memory.

@since 2.1.0

# File lib/mongoid/relations/embedded/many.rb, line 251
def in_memory
  target
end
new(attributes = {}, type = nil)
Alias for: build
pop(count = nil) click to toggle source

Pop documents off the relation. This can be a single document or multiples, and will automatically persist the changes.

@example Pop a single document.

relation.pop

@example Pop multiple documents.

relation.pop(3)

@param [ Integer ] count The number of documents to pop, or 1 if not

provided.

@return [ Document, Array<Document> ] The popped document(s).

@since 3.0.0

# File lib/mongoid/relations/embedded/many.rb, line 270
def pop(count = nil)
  if count
    if docs = target[target.size - count, target.size]
      docs.each { |doc| delete(doc) }
    end
  else
    delete(target[-1])
  end
end
push(*args)
Alias for: <<
substitute(docs) click to toggle source

Substitutes the supplied target documents for the existing documents in the relation.

@example Substitute the relation's target.

person.addresses.substitute([ address ])

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

@return [ Many ] The proxied relation.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 291
def substitute(docs)
  batch_replace(docs)
  self
end
unscoped() click to toggle source

Return the relation with all previous scoping removed. This is the exact representation of the docs in the database.

@example Get the unscoped documents.

person.addresses.unscoped

@return [ Criteria ] The unscoped relation.

@since 2.4.0

# File lib/mongoid/relations/embedded/many.rb, line 305
def unscoped
  criterion = klass.unscoped
  criterion.embedded = true
  criterion.documents = _unscoped.delete_if(&:marked_for_destruction?)
  criterion
end

Private Instance Methods

_unscoped() click to toggle source

Get the internal unscoped documents.

@example Get the unscoped documents.

relation._unscoped

@return [ Array<Document> ] The unscoped documents.

@since 2.4.0

# File lib/mongoid/relations/embedded/many.rb, line 479
def _unscoped
  @_unscoped ||= []
end
_unscoped=(docs) click to toggle source

Set the internal unscoped documents.

@example Set the unscoped documents.

relation._unscoped = docs

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

@return [ Array<Document ] The unscoped docs.

@since 2.4.0

# File lib/mongoid/relations/embedded/many.rb, line 493
def _unscoped=(docs)
  @_unscoped = docs
end
append(document) click to toggle source

Appends the document to the target array, updating the index on the document at the same time.

@example Append to the document.

relation.append(document)

@param [ Document ] document The document to append to the target.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 323
def append(document)
  execute_callback :before_add, document
  target.push(*scope([document]))
  _unscoped.push(document)
  integrate(document)
  document._index = _unscoped.size - 1
  execute_callback :after_add, document
end
binding() click to toggle source

Instantiate the binding associated with this relation.

@example Create the binding.

relation.binding([ address ])

@param [ Array<Document> ] new_target The new documents to bind with.

@return [ Binding ] The many binding.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 342
def binding
  Bindings::Embedded::Many.new(base, target, __metadata)
end
builder(base, meta, object) click to toggle source

Return the builder that is responsible for generating the documents that will be used by this relation.

@example Get the builder.

Embedded::Many.builder(meta, object)

@param [ Document ] base The base document. @param [ Metadata ] meta The metadata of the relation. @param [ Document, Hash ] object A document or attributes to build

with.

@return [ Builder ] A newly instantiated builder object.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 513
def builder(base, meta, object)
  Builders::Embedded::Many.new(base, meta, object)
end
criteria() click to toggle source

Returns the criteria object for the target class with its documents set to target.

@example Get a criteria for the relation.

relation.criteria

@return [ Criteria ] A new criteria.

# File lib/mongoid/relations/embedded/many.rb, line 353
def criteria
  criterion = klass.scoped
  criterion.embedded = true
  criterion.documents = target
  criterion.parent_document = base
  criterion.metadata = relation_metadata
  Many.apply_ordering(criterion, __metadata)
end
delete_one(document) click to toggle source

Deletes one document from the target and unscoped.

@api private

@example Delete one document.

relation.delete_one(doc)

@param [ Document ] document The document to delete.

@since 2.4.7

# File lib/mongoid/relations/embedded/many.rb, line 372
def delete_one(document)
  target.delete_one(document)
  _unscoped.delete_one(document)
  reindex
end
embedded?() click to toggle source

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

@example Is the relation embedded?

Embedded::Many.embedded?

@return [ true ] true.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 526
def embedded?
  true
end
foreign_key_suffix() click to toggle source

Returns the suffix of the foreign key field, either “_id” or “_ids”.

@example Get the suffix for the foreign key.

Referenced::Many.foreign_key_suffix

@return [ nil ] nil.

@since 3.0.0

# File lib/mongoid/relations/embedded/many.rb, line 538
def foreign_key_suffix
  nil
end
integrate(document) click to toggle source

Integrate the document into the relation. will set its metadata and attempt to bind the inverse.

@example Integrate the document.

relation.integrate(document)

@param [ Document ] document The document to integrate.

@since 2.1.0

# File lib/mongoid/relations/embedded/many.rb, line 387
def integrate(document)
  characterize_one(document)
  bind_one(document)
end
macro() click to toggle source

Returns the macro for this relation. Used mostly as a helper in reflection.

@example Get the relation macro.

Mongoid::Relations::Embedded::Many.macro

@return [ Symbol ] :embeds_many

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 551
def macro
  :embeds_many
end
method_missing(name, *args, &block) click to toggle source

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.

@param [ Symbol, String ] name The name of the method. @param [ Array ] args The method args @param [ Proc ] block Optional block to pass.

@return [ Criteria, Object ] A Criteria or return value from the target.

Calls superclass method
# File lib/mongoid/relations/embedded/many.rb, line 402
def method_missing(name, *args, &block)
  return super if target.respond_to?(name)
  klass.send(:with_scope, criteria) do
    criteria.public_send(name, *args, &block)
  end
end
nested_builder(metadata, attributes, options) click to toggle source

Return the nested builder that is responsible for generating the documents that will be used by this relation.

@example Get the nested builder.

NestedAttributes::Many.builder(attributes, options)

@param [ Metadata ] metadata The relation metadata. @param [ Hash ] attributes The attributes to build with. @param [ Hash ] options The builder options.

@option options [ true, false ] :allow_destroy Can documents be

deleted?

@option options [ Integer ] :limit Max number of documents to

create at once.

@option options [ Proc, Symbol ] :reject_if If documents match this

option then they are ignored.

@option options [ true, false ] :update_only Only existing documents

can be modified.

@return [ NestedBuilder ] The nested attributes builder.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 577
def nested_builder(metadata, attributes, options)
  Builders::NestedAttributes::Many.new(metadata, attributes, options)
end
path(document) click to toggle source

Get the path calculator for the supplied document.

@example Get the path calculator.

Proxy.path(document)

@param [ Document ] document The document to calculate on.

@return [ Mongoid::Atomic::Paths::Embedded::Many ]

The embedded many atomic path calculator.

@since 2.1.0

# File lib/mongoid/relations/embedded/many.rb, line 592
def path(document)
  Mongoid::Atomic::Paths::Embedded::Many.new(document)
end
persistable?() click to toggle source

Are we able to persist this relation?

@example Can we persist the relation?

relation.persistable?

@return [ true, false ] If the relation is persistable.

@since 2.1.0

# File lib/mongoid/relations/embedded/many.rb, line 417
def persistable?
  base.persisted? && !_binding?
end
reindex() click to toggle source

Reindex all the target elements. This is useful when performing operations on the proxied target directly and the indices need to match that on the database side.

@example Reindex the relation.

person.addresses.reindex

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 429
def reindex
  _unscoped.each_with_index do |doc, index|
    doc._index = index
  end
end
remove_all(conditions = {}, method = :delete) click to toggle source

Remove all documents from the relation, either with a delete or a destroy depending on what this was called through.

@example Destroy documents from the relation.

relation.remove_all({ :num => 1 }, true)

@param [ Hash ] conditions Conditions to filter by. @param [ true, false ] destroy If true then destroy, else delete.

@return [ Integer ] The number of documents removed.

# File lib/mongoid/relations/embedded/many.rb, line 464
def remove_all(conditions = {}, method = :delete)
  criteria = where(conditions || {})
  removed = criteria.size
  batch_remove(criteria, method)
  removed
end
scope(docs) click to toggle source

Apply the metadata ordering or the default scoping to the provided documents.

@example Apply scoping.

person.addresses.scope(target)

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

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

@since 2.4.0

# File lib/mongoid/relations/embedded/many.rb, line 446
def scope(docs)
  return docs unless __metadata.order || __metadata.klass.default_scoping?
  crit = __metadata.klass.order_by(__metadata.order)
  crit.embedded = true
  crit.documents = docs
  crit.entries
end
stores_foreign_key?() click to toggle source

Tells the caller if this relation is one that stores the foreign key on its own objects.

@example Does this relation store a foreign key?

Embedded::Many.stores_foreign_key?

@return [ false ] false.

@since 2.0.0.rc.1

# File lib/mongoid/relations/embedded/many.rb, line 605
def stores_foreign_key?
  false
end
valid_options() click to toggle source

Get the valid options allowed with this relation.

@example Get the valid options.

Relation.valid_options

@return [ Array<Symbol> ] The valid options.

@since 2.1.0

# File lib/mongoid/relations/embedded/many.rb, line 617
def valid_options
  [
    :as, :cascade_callbacks, :cyclic, :order, :store_as,
    :before_add, :after_add, :before_remove, :after_remove
  ]
end
validation_default() click to toggle source

Get the default validation setting for the relation. Determines if by default a validates associated will occur.

@example Get the validation default.

Proxy.validation_default

@return [ true, false ] The validation default.

@since 2.1.9

# File lib/mongoid/relations/embedded/many.rb, line 633
def validation_default
  true
end