Class: Mongoid::Relations::Embedded::Many

Inherits:
Many show all
Includes:
Atomic
Defined in:
lib/mongoid/relations/embedded/many.rb

Overview

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

Constant Summary

Constants included from Atomic

Atomic::MODIFIERS

Instance Attribute Summary

Attributes inherited from Proxy

#base, #loaded, #metadata, #target

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Many

#build, #exists?, #find_or_create_by, #find_or_initialize_by, #nil?, #respond_to?, #serializable_hash, #size

Methods inherited from Proxy

#init

Constructor Details

#initialize(base, target, metadata) ⇒ Many

Instantiate a new embeds_many relation.

Examples:

Create the new relation.

Many.new(person, addresses, )

Parameters:

  • base (Document)

    The document this relation hangs off of.

  • target (Array<Document>)

    The child documents of the relation.

  • metadata (Metadata)

    The relation’s metadata



207
208
209
210
211
212
213
214
215
# File 'lib/mongoid/relations/embedded/many.rb', line 207

def initialize(base, target, )
  init(base, target, ) do
    target.each_with_index do |doc, index|
      characterize_one(doc)
      doc.parentize(base)
      doc._index = index
    end
  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:



353
354
355
356
357
358
359
# File 'lib/mongoid/relations/embedded/many.rb', line 353

def method_missing(name, *args, &block)
  load!(:binding => true) and return super if target.respond_to?(name)
  klass = .klass
  klass.send(:with_scope, criteria) do
    criteria.send(name, *args, &block)
  end
end

Class Method Details

.builder(meta, object) ⇒ Builder

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

Examples:

Get the builder.

Embedded::Many.builder(meta, object)

Parameters:

  • meta (Metadata)

    The metadata of the relation.

  • object (Document, Hash)

    A document or attributes to build with.

Returns:

  • (Builder)

    A newly instantiated builder object.

Since:

  • 2.0.0.rc.1



427
428
429
# File 'lib/mongoid/relations/embedded/many.rb', line 427

def builder(meta, object)
  Builders::Embedded::Many.new(meta, object)
end

.embedded?true

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

Examples:

Is the relation embedded?

Embedded::Many.embedded?

Returns:

  • (true)

    true.

Since:

  • 2.0.0.rc.1



440
441
442
# File 'lib/mongoid/relations/embedded/many.rb', line 440

def embedded?
  true
end

.macroSymbol

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

Examples:

Get the relation macro.

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

Returns:

Since:

  • 2.0.0.rc.1



453
454
455
# File 'lib/mongoid/relations/embedded/many.rb', line 453

def macro
  :embeds_many
end

.nested_builder(metadata, attributes, options) ⇒ NestedBuilder

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

Examples:

Get the nested builder.

NestedAttributes::Many.builder(attributes, options)

Parameters:

  • metadata (Metadata)

    The relation metadata.

  • attributes (Hash)

    The attributes to build with.

  • options (Hash)

    The builder options.

Options Hash (options):

  • :allow_destroy (true, false)

    Can documents be deleted?

  • :limit (Integer)

    Max number of documents to create at once.

  • :reject_if (Proc, Symbol)

    If documents match this option then they are ignored.

  • :update_only (true, false)

    Only existing documents can be modified.

Returns:

Since:

  • 2.0.0.rc.1



479
480
481
# File 'lib/mongoid/relations/embedded/many.rb', line 479

def nested_builder(, attributes, options)
  Builders::NestedAttributes::Many.new(, attributes, options)
end

.stores_foreign_key?false

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

Examples:

Does this relation store a foreign key?

Embedded::Many.stores_foreign_key?

Returns:

  • (false)

    false.

Since:

  • 2.0.0.rc.1



492
493
494
# File 'lib/mongoid/relations/embedded/many.rb', line 492

def stores_foreign_key?
  false
end

Instance Method Details

#<<(*args) ⇒ Object

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

Examples:

Append a document.

person.addresses << address

Push a document.

person.addresses.push(address)

Concat with other documents.

person.addresses.concat([ address_one, address_two ])

Parameters:



24
25
26
27
28
29
30
31
32
33
# File 'lib/mongoid/relations/embedded/many.rb', line 24

def <<(*args)
  options = default_options(args)
  atomically(:$pushAll) do
    args.flatten.each do |doc|
      return doc unless doc
      append(doc, options)
      doc.save if base.persisted? && !options[:binding]
    end
  end
end

#as_documentArray<Hash>

Get this relation as as its representation in the database.

Examples:

Convert the relation to an attributes hash.

person.addresses.as_document

Returns:

  • (Array<Hash>)

    The relation as stored in the db.

Since:

  • 2.0.0.rc.1



267
268
269
270
271
272
273
# File 'lib/mongoid/relations/embedded/many.rb', line 267

def as_document
  target.inject([]) do |attributes, doc|
    attributes.tap do |attr|
      attr << doc.as_document
    end
  end
end

#bind(options = {}) ⇒ Object

Binds the base object to the inverse of the relation. This is so we are referenced to the actual objects themselves and dont hit the database twice when setting the relations up.

This is called after first creating the relation, or if a new object is set on the relation.

Examples:

Bind the relation.

person.addresses.bind(:continue => true)

Parameters:

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

    The options to bind with.

Options Hash (options):

  • :binding (true, false)

    Are we in build mode?

  • :continue (true, false)

    Continue binding the inverse?

Since:

  • 2.0.0.rc.1



52
53
54
55
56
57
# File 'lib/mongoid/relations/embedded/many.rb', line 52

def bind(options = {})
  binding.bind(options)
  if base.persisted? && !options[:binding]
    atomically(:$set) { target.each(&:save) }
  end
end

#bind_one(document, options = {}) ⇒ Object

Bind the inverse relation between a single document in this proxy instead of the entire target.

Used when appending to the target instead of setting the entire thing.

Examples:

Bind a single document.

person.addressses.bind_one(address)

Parameters:

  • document (Document)

    The document to bind.

Since:

  • 2.0.0.rc.1



71
72
73
# File 'lib/mongoid/relations/embedded/many.rb', line 71

def bind_one(document, options = {})
  binding.bind_one(document, options)
end

#clearMany

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

Examples:

Clear the relation.

person.addresses.clear

Returns:

  • (Many)

    The empty relation.



82
83
84
# File 'lib/mongoid/relations/embedded/many.rb', line 82

def clear
  load! and substitute(nil)
end

#countInteger

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.

Examples:

Get the count of persisted documents.

person.addresses.count

Returns:

  • (Integer)

    The total number of persisted embedded docs, as flagged by the #persisted? method.



96
97
98
# File 'lib/mongoid/relations/embedded/many.rb', line 96

def count
  target.select(&:persisted?).size
end

#create(attributes = {}, type = nil, &block) ⇒ Document

Create a new document in the relation. This is essentially the same as doing a #build then #save on the new document.

Examples:

Create a new document in the relation.

person.movies.create(:name => "Bozo")

Parameters:

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

    The attributes to build the document with.

  • type (Class) (defaults to: nil)

    Optional class to create the document with.

Returns:

  • (Document)

    The newly created document.



110
111
112
# File 'lib/mongoid/relations/embedded/many.rb', line 110

def create(attributes = {}, type = nil, &block)
  build(attributes, type, &block).tap(&:save)
end

#create!(attributes = {}, type = nil, &block) ⇒ Document

Create a new document in the relation. This is essentially the same as doing a #build then #save on the new document. If validation failed on the document an error will get raised.

Examples:

Create the document.

person.addresses.create!(:street => "Unter der Linden")</tt>

Parameters:

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

    The attributes to build the document with.

  • type (Class) (defaults to: nil)

    Optional class to create the document with.

Returns:

  • (Document)

    The newly created document.

Raises:



127
128
129
# File 'lib/mongoid/relations/embedded/many.rb', line 127

def create!(attributes = {}, type = nil, &block)
  build(attributes, type, &block).tap(&:save!)
end

#delete(document) ⇒ Document?

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

Examples:

Delete the document from the relation.

person.addresses.delete(address)

Parameters:

  • document (Document)

    The document to be deleted.

Returns:

  • (Document, nil)

    The deleted document or nil if nothing deleted.

Since:

  • 2.0.0.rc.1



142
143
144
# File 'lib/mongoid/relations/embedded/many.rb', line 142

def delete(document)
  target.delete(document).tap { reindex }
end

#delete_all(conditions = {}) ⇒ Integer

Delete all the documents in the association without running callbacks.

Examples:

Delete all documents from the relation.

person.addresses.delete_all

Conditionally delete documents from the relation.

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

Parameters:

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

    Conditions on which documents to delete.

Returns:

  • (Integer)

    The number of documents deleted.



157
158
159
# File 'lib/mongoid/relations/embedded/many.rb', line 157

def delete_all(conditions = {})
  atomically(:$pull) { remove_all(conditions, :delete) }
end

#destroy_all(conditions = {}) ⇒ Integer

Destroy all the documents in the association whilst running callbacks.

Examples:

Destroy all documents from the relation.

person.addresses.destroy_all

Conditionally destroy documents from the relation.

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

Parameters:

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

    Conditions on which documents to destroy.

Returns:

  • (Integer)

    The number of documents destroyed.



172
173
174
# File 'lib/mongoid/relations/embedded/many.rb', line 172

def destroy_all(conditions = {})
  atomically(:$pull) { remove_all(conditions, :destroy) }
end

#find(*args) ⇒ Array<Document>, Document

Finds a document in this association through several different methods.

Examples:

Find a document by its id.

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

Find documents for multiple ids.

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

Find documents based on conditions.

person.addresses.find(:all, :conditions => { :number => 10 })
person.addresses.find(:first, :conditions => { :number => 10 })
person.addresses.find(:last, :conditions => { :number => 10 })

Parameters:

Returns:



193
194
195
# File 'lib/mongoid/relations/embedded/many.rb', line 193

def find(*args)
  criteria.find(*args)
end

#load!(options = {}) ⇒ Many

Will load the target into an array if the target had not already been loaded.

Examples:

Load the relation into memory.

relation.load!

Returns:

  • (Many)

    The relation.

Since:

  • 2.0.0.rc.5



226
227
228
229
230
231
232
233
# File 'lib/mongoid/relations/embedded/many.rb', line 226

def load!(options = {})
  tap do |relation|
    unless relation.loaded?
      relation.bind(options)
      relation.loaded = true
    end
  end
end

#substitute(new_target, options = {}) ⇒ Many

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

Examples:

Substitute the relation’s target.

person.addresses.substitute([ address ])

Parameters:

  • new_target (Array<Document>)

    The replacement array.

  • building (true, false)

    Are we in build mode?

Returns:

  • (Many)

    The proxied relation.

Since:

  • 2.0.0.rc.1



247
248
249
250
251
252
253
254
255
256
257
# File 'lib/mongoid/relations/embedded/many.rb', line 247

def substitute(new_target, options = {})
  old_target = target
  tap do |relation|
    relation.target = new_target || []
    if !new_target.blank?
      atomically(:$set) { rebind(old_target, options) }
    else
      atomically(:$unset) { unbind(old_target, options) }
    end
  end
end

#unbind(old_target, options = {}) ⇒ Object

Unbind the inverse relation from this set of documents. Used when the entire proxy has been cleared, set to nil or empty, or replaced.

Examples:

Unbind the relation.

person.addresses.unbind(target, :continue => false)

Parameters:

  • old_target (Array<Document>)

    The relations previous target.

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

    The options to bind with.

Options Hash (options):

  • :binding (true, false)

    Are we in build mode?

  • :continue (true, false)

    Continue binding the inverse?

Since:

  • 2.0.0.rc.1



289
290
291
292
293
294
295
296
# File 'lib/mongoid/relations/embedded/many.rb', line 289

def unbind(old_target, options = {})
  binding(old_target).unbind(options)
  if base.persisted?
    old_target.each do |doc|
      doc.delete unless doc.destroyed?
    end
  end
end