module Mongoid::Relations::Macros::ClassMethods

Public Instance Methods

belongs_to(name, options = {}, &block) click to toggle source

Adds a relational association from the child Document to a Document in another database or collection.

@example Define the relation.

class Game
  include Mongoid::Document
  belongs_to :person
end

class Person
  include Mongoid::Document
  has_one :game
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

# File lib/mongoid/relations/macros.rb, line 137
def belongs_to(name, options = {}, &block)
  meta = reference_one_to_one(name, options, Referenced::In, &block)
  aliased_fields[name.to_s] = meta.foreign_key
  touchable(meta)
  add_counter_cache_callbacks(meta) if meta.counter_cached?
  meta
end
embedded_in(name, options = {}, &block) click to toggle source

Adds the relation back to the parent document. This macro is necessary to set the references from the child back to the parent document. If a child does not define this relation calling persistence methods on the child object will cause a save to fail.

@example Define the relation.

class Person
  include Mongoid::Document
  embeds_many :addresses
end

class Address
  include Mongoid::Document
  embedded_in :person
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

# File lib/mongoid/relations/macros.rb, line 52
def embedded_in(name, options = {}, &block)
  meta = characterize(name, Embedded::In, options, &block)
  self.embedded = true
  relate(name, meta)
  builder(name, meta).creator(name, meta)
  touchable(meta)
  add_counter_cache_callbacks(meta) if meta.counter_cached?
  meta
end
embeds_many(name, options = {}, &block) click to toggle source

Adds the relation from a parent document to its children. The name of the relation needs to be a pluralized form of the child class name.

@example Define the relation.

class Person
  include Mongoid::Document
  embeds_many :addresses
end

class Address
  include Mongoid::Document
  embedded_in :person
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

# File lib/mongoid/relations/macros.rb, line 81
def embeds_many(name, options = {}, &block)
  meta = characterize(name, Embedded::Many, options, &block)
  self.cyclic = true if options[:cyclic]
  relate(name, meta)
  embed(name, meta)
  validates_relation(meta)
  meta
end
embeds_one(name, options = {}, &block) click to toggle source

Adds the relation from a parent document to its child. The name of the relation needs to be a singular form of the child class name.

@example Define the relation.

class Person
  include Mongoid::Document
  embeds_one :name
end

class Name
  include Mongoid::Document
  embedded_in :person
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

# File lib/mongoid/relations/macros.rb, line 109
def embeds_one(name, options = {}, &block)
  meta = characterize(name, Embedded::One, options, &block)
  self.cyclic = true if options[:cyclic]
  relate(name, meta)
  embed(name, meta)
  builder(name, meta).creator(name, meta)
  validates_relation(meta)
  meta
end
has_and_belongs_to_many(name, options = {}, &block) click to toggle source

Adds a relational many-to-many association between many of this Document and many of another Document.

@example Define the relation.

class Person
  include Mongoid::Document
  has_and_belongs_to_many :preferences
end

class Preference
  include Mongoid::Document
  has_and_belongs_to_many :people
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

@since 2.0.0.rc.1

# File lib/mongoid/relations/macros.rb, line 193
def has_and_belongs_to_many(name, options = {}, &block)
  meta = characterize(name, Referenced::ManyToMany, options, &block)
  relate(name, meta)
  reference(meta, Array)
  autosave(meta)
  validates_relation(meta)
  synced(meta)
  meta
end
has_many(name, options = {}, &block) click to toggle source

Adds a relational association from a parent Document to many Documents in another database or collection.

@example Define the relation.

class Person
  include Mongoid::Document
  has_many :posts
end

class Game
  include Mongoid::Document
  belongs_to :person
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

# File lib/mongoid/relations/macros.rb, line 163
def has_many(name, options = {}, &block)
  meta = characterize(name, Referenced::Many, options, &block)
  relate(name, meta)
  ids_getter(name, meta).ids_setter(name, meta)
  reference(meta)
  autosave(meta)
  validates_relation(meta)
  meta
end
has_one(name, options = {}, &block) click to toggle source

Adds a relational association from the child Document to a Document in another database or collection.

@example Define the relation.

class Game
  include Mongoid::Document
  belongs_to :person
end

class Person
  include Mongoid::Document
  has_one :game
end

@param [ Symbol ] name The name of the relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

# File lib/mongoid/relations/macros.rb, line 221
def has_one(name, options = {}, &block)
  reference_one_to_one(name, options, Referenced::One, &block)
end

Private Instance Methods

characterize(name, relation, options, &block) click to toggle source

Create the metadata for the relation.

@api private

@example Create the metadata.

Person.characterize(:posts, Referenced::Many, {})

@param [ Symbol ] name The name of the relation. @param [ Object ] relation The type of relation. @param [ Hash ] options The relation options. @param [ Proc ] block Optional block for defining extensions.

@return [ Metadata ] The metadata for the relation.

# File lib/mongoid/relations/macros.rb, line 240
def characterize(name, relation, options, &block)
  Metadata.new({
    relation: relation,
    extend: create_extension_module(name, &block),
    inverse_class_name: self.name,
    name: name
  }.merge(options))
end
create_extension_module(name, &block) click to toggle source

Generate a named extension module suitable for marshaling

@api private

@example Get the module.

Person.create_extension_module(:posts, &block)

@param [ Symbol ] name The name of the relation. @param [ Proc ] block Optional block for defining extensions.

@return [ Module, nil ] The extension or nil.

@since 2.1.0

# File lib/mongoid/relations/macros.rb, line 262
def create_extension_module(name, &block)
  if block
    extension_module_name =
      "#{self.to_s.demodulize}#{name.to_s.camelize}RelationExtension"
    silence_warnings do
      self.const_set(extension_module_name, Module.new(&block))
    end
    "#{self}::#{extension_module_name}".constantize
  end
end
embed(name, metadata) click to toggle source

Add an embedded relation metadata to the embedded relations.

@api private

@example Add the metadata to embedded relations.

Person.embed("addresses", metadata)

@param [ String ] name The name of the relation. @param [ Metadata ] metadata The relation metadata.

@since 3.0.0

# File lib/mongoid/relations/macros.rb, line 284
def embed(name, metadata)
  self.embedded_relations = embedded_relations.merge(name.to_s => metadata)
  aliased_fields[name.to_s] = metadata.store_as if metadata.store_as
end
reference(metadata, type = Object) click to toggle source

Defines a field to be used as a foreign key in the relation and indexes it if defined.

@api private

@example Set up the relational fields and indexes.

Person.reference(metadata)

@param [ Metadata ] metadata The metadata for the relation.

# File lib/mongoid/relations/macros.rb, line 298
def reference(metadata, type = Object)
  polymorph(metadata).cascade(metadata)
  if metadata.relation.stores_foreign_key?
    key = metadata.foreign_key
    field(
      key,
      type: type,
      identity: true,
      overwrite: true,
      metadata: metadata,
      default: metadata.foreign_key_default
    )
    if metadata.indexed?
      if metadata.polymorphic?
        index({ key => 1, metadata.inverse_type => 1 }, { background: true })
      else
        index({ key => 1 }, { background: true })
      end
    end
  end
end
reference_one_to_one(name, options, relation, &block) click to toggle source

Handle common behaviour for referenced 1-1 relation setup.

@api private

@example Add the one to one behaviour.

Model.reference_one_to_one(:name, meta)

@param [ Symbol ] name The name of the relation. @param [ Metadata ] meta The relation metadata.

@return [ Class ] The model class.

@since 3.0.0

# File lib/mongoid/relations/macros.rb, line 333
def reference_one_to_one(name, options, relation, &block)
  meta = characterize(name, relation, options, &block)
  relate(name, meta)
  reference(meta)
  builder(name, meta).creator(name, meta).autosave(meta)
  validates_relation(meta)
  meta
end
relate(name, metadata) click to toggle source

Creates a relation for the given name, metadata and relation. It adds the metadata to the relations hash and has the accessors set up.

@example Set up the relation and accessors.

Person.relate(:addresses, Metadata)

@param [ Symbol ] name The name of the relation. @param [ Metadata ] metadata The metadata for the relation.

# File lib/mongoid/relations/macros.rb, line 350
def relate(name, metadata)
  self.relations = relations.merge(name.to_s => metadata)
  getter(name, metadata).setter(name, metadata).existence_check(name)
end