123456789_123456789_123456789_123456789_123456789_

Class: Mongoid::Association::Many

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Forwardable, Proxy, Forwardable
Instance Chain:
Inherits: Mongoid::Association::Proxy
Defined in: lib/mongoid/association/many.rb

Overview

This is the superclass for all many to one and many to many association proxies.

Constant Summary

Proxy - Inherited

KEEPER_METHODS

Class Method Summary

Proxy - Inherited

.apply_ordering

Apply ordering to the criteria if it was defined on the association.

.new

Sets the target and the association metadata properties.

Instance Attribute Summary

Proxy - Inherited

#_association,
#_base

Model instance for the base of the association.

#_target

Model instance for one to one associations, or array of model instances for one to many associations, for the target of the association.

::Mongoid::Threaded::Lifecycle - Included

#_assigning

Begin the assignment of attributes.

#_assigning?

Is the current thread in assigning mode?

#_binding

Execute a block in binding mode.

#_binding?

Is the current thread in binding mode?

#_building

Execute a block in building mode.

#_building?

Is the current thread in building mode?

#_creating?

Is the current thread in creating mode?

#_loading

Execute a block in loading mode.

#_loading?

Is the current thread in loading mode?

Instance Method Summary

Proxy - Inherited

#extend_proxies

Allow extension to be an array and extend each module.

#extend_proxy,
#klass

Get the class from the association, or return nil if no association present.

#reset_unloaded

Resets the criteria inside the association proxy.

#substitutable

The default substitutable object for an association proxy is the clone of the target.

Marshalable - Included

#marshal_dump

Provides the data needed to Marshal.dump an association proxy.

#marshal_load

Takes the provided data and sets it back on the proxy.

Constructor Details

This class inherits a constructor from Mongoid::Association::Proxy

Instance Attribute Details

#blank?true | false (readonly)

Is the association empty?

Examples:

Is the association empty??

person.addresses.blank?

Returns:

  • (true | false)

    If the association is empty or not.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 22

def blank?
  !any?
end

#nil?false (readonly)

This proxy can never be nil.

Examples:

Is the proxy nil?

relation.nil?

Returns:

  • (false)

    Always false.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 124

def nil?
  false
end

Instance Method Details

#_session (private)

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 196

def _session
  _base.send(:_session)
end

#analyze_loaded_target(timestamp_column) (private)

Return a 2-tuple of the number of elements in the relation, and the largest timestamp value.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 242

def analyze_loaded_target(timestamp_column)
  newest = _target.select { |elem| elem.respond_to?(timestamp_column) }
                  .max { |a, b| a[timestamp_column] <=> b[timestamp_column] }
  [ _target.length, newest ? newest[timestamp_column] : nil ]
end

#analyze_unloaded_target(timestamp_column) (private)

Returns a 2-tuple of the number of elements in the relation, and the largest timestamp value. This will query the database to perform a $sum and a $max.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 251

def analyze_unloaded_target(timestamp_column)
  pipeline = criteria
    .group(_id: nil,
           count: { '$sum' => 1 },
           latest: { '$max' => "$#{timestamp_column}" })
    .pipeline

  result = klass.collection.aggregate(pipeline).to_a.first

  result ? [ result["count"], result["latest"] ] : [ 0 ]
end

#cache_version(timestamp_column = :updated_at) ⇒ String

For compatibility with Rails’ caching. Returns a string based on the given timestamp, and includes the number of records in the relation in the version.

Parameters:

  • timestamp_column (String | Symbol) (defaults to: :updated_at)

    the timestamp column to use when constructing the key.

Returns:

  • (String)

    the cache version string

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 189

def cache_version(timestamp_column = :updated_at)
  @cache_version ||= {}
  @cache_version[timestamp_column] ||= compute_cache_version(timestamp_column)
end

#compute_cache_version(timestamp_column) ⇒ String (private)

Computes the cache version for the relation using the given timestamp colum; see #cache_version.

Parameters:

  • timestamp_column (String | Symbol)

    the timestamp column to use when constructing the key.

Returns:

  • (String)

    the cache version string

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 222

def compute_cache_version(timestamp_column)
  timestamp_column = timestamp_column.to_s

  loaded = _target.respond_to?(:_loaded?) ?
              _target._loaded? :   # has_many
              true                 # embeds_many

  size, timestamp = loaded ?
    analyze_loaded_target(timestamp_column) :
    analyze_unloaded_target(timestamp_column)

  if timestamp
    "#{size}-#{timestamp.utc.to_formatted_s(klass.cache_timestamp_format)}"
  else
    size.to_s
  end
end

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

Creates a new document on the references many association. This will save the document if the parent has been persisted.

Examples:

Create and save the new document.

person.posts.create(:text => "Testing")

Parameters:

  • attributes (Hash) (defaults to: nil)

    The attributes to create with.

  • type (Class) (defaults to: nil)

    The optional type of document to create.

Returns:

  • (Document)

    The newly created document.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 36

def create(attributes = nil, type = nil, &block)
  if attributes.is_a?(::Array)
    attributes.map { |attrs| create(attrs, type, &block) }
  else
    doc = build(attributes, type, &block)
    _base.persisted? ? doc.save : raise_unsaved(doc)
    doc
  end
end

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

Creates a new document on the references many association. This will save the document if the parent has been persisted and will raise an error if validation fails.

Examples:

Create and save the new document.

person.posts.create!(:text => "Testing")

Parameters:

  • attributes (Hash) (defaults to: nil)

    The attributes to create with.

  • type (Class) (defaults to: nil)

    The optional type of document to create.

Returns:

  • (Document)

    The newly created document.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 59

def create!(attributes = nil, type = nil, &block)
  if attributes.is_a?(::Array)
    attributes.map { |attrs| create!(attrs, type, &block) }
  else
    doc = build(attributes, type, &block)

    Array(doc).each do |doc|
      doc.try(:run_pending_callbacks)
    end

    _base.persisted? ? doc.save! : raise_unsaved(doc)
    doc
  end
end

#find_or(method, attrs = {}, type = nil, &block) ⇒ Document (private)

Find the first object given the supplied attributes or create/initialize it.

Examples:

Find or create|initialize.

person.addresses.find_or(:create, :street => "Bond")

@param [ Symbol ] method The method name, create or new.
@param [ Hash ] attrs The attributes to search or build with.
@param [ Class ] type The optional subclass to build.

Returns:

  • (Document)

    A matching document or a new/created one.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 210

def find_or(method, attrs = {}, type = nil, &block)
  attrs[klass.discriminator_key] = type.discriminator_value if type
  where(attrs).first || send(method, attrs, type, &block)
end

#find_or_create_by(attrs = {}, type = nil, &block) ⇒ Document

Find the first document given the conditions, or creates a new document with the conditions that were supplied.

@param [ Hash ] attrs The attributes to search or create with.
@param [ Class ] type The optional type of document to create.

Examples:

Find or create.

person.posts.find_or_create_by(:title => "Testing")

Returns:

  • (Document)

    An existing document or newly created one.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 84

def find_or_create_by(attrs = {}, type = nil, &block)
  find_or(:create, attrs, type, &block)
end

#find_or_create_by!(attrs = {}, type = nil, &block) ⇒ Document

Find the first document given the conditions, or creates a new document with the conditions that were supplied. This will raise an error if validation fails.

Examples:

Find or create.

person.posts.find_or_create_by!(:title => "Testing")

Parameters:

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

    The attributes to search or create with.

  • type (Class) (defaults to: nil)

    The optional type of document to create.

Returns:

  • (Document)

    An existing document or newly created one.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 100

def find_or_create_by!(attrs = {}, type = nil, &block)
  find_or(:create!, attrs, type, &block)
end

#find_or_initialize_by(attrs = {}, type = nil, &block) ⇒ Document

Find the first ::Mongoid::Document given the conditions, or instantiates a new document with the conditions that were supplied

Examples:

Find or initialize.

person.posts.find_or_initialize_by(:title => "Test")

Parameters:

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

    The attributes to search or initialize with.

  • type (Class) (defaults to: nil)

    The optional subclass to build.

Returns:

  • (Document)

    An existing document or newly instantiated one.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 114

def find_or_initialize_by(attrs = {}, type = nil, &block)
  find_or(:build, attrs, type, &block)
end

#respond_to?(name, include_private = false) ⇒ true | false

Since method_missing is overridden we should override this as well.

Examples:

Does the proxy respond to the method?

relation.respond_to?(:name)

Parameters:

  • name (Symbol)

    The method name.

  • include_private (true | false) (defaults to: false)

    Whether to include private methods.

Returns:

  • (true | false)

    If the proxy responds to the method.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 137

def respond_to?(name, include_private = false)
  [].respond_to?(name, include_private) ||
    klass.respond_to?(name, include_private) || super
end

#scopedCriteria

This is public access to the association’s criteria.

Examples:

Get the scoped association.

relation.scoped

Returns:

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 148

def scoped
  criteria
end

#serializable_hash(options = {}) ⇒ Hash

Gets the document as a serializable hash, used by ActiveModel’s JSON and XML serializers. This override is just to be able to pass the :include and :except options to get associations in the hash.

Examples:

Get the serializable hash.

relation.serializable_hash

Parameters:

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

    The options to pass.

Options Hash (options):

Returns:

  • (Hash)

    The documents, ready to be serialized.

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 166

def serializable_hash(options = {})
  _target.map { |document| document.serializable_hash(options) }
end

#unscopedCriteria

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

Examples:

Get the unscoped criteria.

person.addresses.unscoped

Returns:

[ GitHub ]

  
# File 'lib/mongoid/association/many.rb', line 177

def unscoped
  criteria.unscoped
end