123456789_123456789_123456789_123456789_123456789_

Class: Mongoid::Association::Referenced::HasAndBelongsToMany

Overview

The HasAndBelongsToMany type association.

Constant Summary

::Mongoid::Association::Relatable - Included

PRIMARY_KEY_DEFAULT, SHARED_OPTIONS

Instance Attribute Summary

::Mongoid::Association::Relatable - Included

#destructive?

Whether the dependent method is destructive.

#in_to?

Is this association an embedded_in or belongs_to association?

#many?

Is this association an embeds_many or has_many association?

#name

The name of the association.

#one?

Is this association an embeds_one or has_one association?

#options

The options on this association.

#parent_inclusions

The associations above this one in the inclusion tree.

#parent_inclusions=

The associations above this one in the inclusion tree.

#validate?

Whether the associated object(s) should be validated.

::Mongoid::Association::Options - Included

#autobuilding?

Whether the association is autobuilding.

#autosave

::Mongoid::Association::Options to save any loaded members and destroy members that are marked for destruction when the parent object is saved.

#autosave?

Alias for Options#autosave.

#cascading_callbacks?

Whether the association has callbacks cascaded down from the parent.

#counter_cached?

Whether the association is counter-cached.

#cyclic?

Is the association cyclic.

#forced_nil_inverse?

Whether the association has forced nil inverse (So no foreign keys are saved).

#indexed?

Whether to index the primary or foreign key field.

#polymorphic?

Whether this association is polymorphic.

#touchable?

Whether the association object should be automatically touched when its inverse object is updated.

Instance Method Summary

Buildable - Included

#build

This builder either takes a hash and queries for the object or an array of documents, where it will just return them.

#query?

::Mongoid::Association::Relatable - Included

#==

Compare this association to another.

#bindable?

Whether trying to bind an object using this association should raise an error.

#class_name
#counter_cache_column_name

Get the counter cache column name.

#create_relation

Create an association proxy object using the owner and target.

#extension

Get the extension.

#foreign_key_check

Get the name of the method to check if the foreign key has changed.

#foreign_key_setter

The name of the foreign key setter method.

#get_callbacks

Get the callbacks for a given type.

#initialize

Initialize the ::Mongoid::Association.

#inverse

Get the inverse name.

#inverse_association

Get the inverse’s association metadata.

#inverse_class

The class of the object owning this association.

#inverse_class_name

The class name of the object owning this association.

#inverse_klass
#inverse_setter

The name of the inverse setter method.

#inverse_type

Get the inverse type.

#inverse_type_setter

Gets the setter for the field that sets the type of document on a polymorphic association.

#inverses

Get the inverse names.

#key

The foreign key field if this association stores a foreign key.

#klass
#path

The atomic path for this association.

#relation_class

The class of the association object(s).

#relation_class_name
The class name, possibly unqualified or

prefixed, of the association object(s).

#setter

The name of the setter on this object for assigning an associated object.

#type_setter

Get the type setter.

#create_extension!, #default_inverse, #define_autosaver!, #define_builder!, #define_counter_cache_callbacks!, #define_creator!, #define_dependency!, #define_existence_check!, #define_getter!, #define_ids_getter!, #define_ids_setter!, #define_setter!, #define_touchable!,
#inverse_association_classes

Gets the model classes with inverse associations of this model.

#namespace_hierarchy

Returns an array of classes/modules forming the namespace hierarchy where symbols referenced in the provided class/module would be looked up by Ruby.

#polymorph!,
#resolve_name

Resolves the given class/module name in the context of the specified module, as Ruby would when a constant is referenced in the source.

#setup_index!, #validate!

::Mongoid::Association::Options - Included

#as

Returns the name of the parent to a polymorphic child.

#dependent

Specify what happens to the associated object when the owner is destroyed.

#inverse_of

The name the owning object uses to refer to this association.

#order

The custom sorting options on the association.

#primary_key

::Mongoid assumes that the field used to hold the primary key of the association is id.

#store_as

The store_as option.

#touch_field

The field for saving the associated object’s type.

#type

The field for saving the associated object’s type.

::Mongoid::Association::Constrainable - Included

#convert_to_foreign_key

Convert the supplied object to the appropriate type to set as the foreign key for an association.

#convert_polymorphic

Instance Attribute Details

#embedded?false (readonly)

Is this association type embedded?

Returns:

  • (false)

    Always false.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 73

def embedded?; false; end

#forced_nil_inverse?true | false (readonly)

Are ids only saved on this side of the association?

Returns:

  • (true | false)

    Whether this association has a forced nil inverse.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 83

def forced_nil_inverse?
  @forced_nil_inverse ||= @options.key?(:inverse_of) && !@options[:inverse_of]
end

#stores_foreign_key?true (readonly)

Does this association type store the foreign key?

Returns:

  • (true)

    Always true.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 90

def stores_foreign_key?; true; end

Instance Method Details

#bindable?(doc) ⇒ true | false

Whether trying to bind an object using this association should raise an error.

Parameters:

  • doc (Document)

    The document to be bound.

Returns:

  • (true | false)

    Whether the document can be bound.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 136

def bindable?(doc)
  forced_nil_inverse? || (!!inverse && doc.fields.keys.include?(foreign_key))
end

#create_foreign_key_field! (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 233

def create_foreign_key_field!
  inverse_class.aliased_associations[foreign_key] = name.to_s
  @owner_class.field(
      foreign_key,
      type: FOREIGN_KEY_FIELD_TYPE,
      identity: true,
      overwrite: true,
      association: self,
      default: nil
  )
end

#criteria(base, id_list = nil) ⇒ Mongoid::Criteria

The criteria used for querying this association.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 110

def criteria(base, id_list = nil)
  query_criteria(id_list || base.send(foreign_key))
end

#default_foreign_key_field (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 201

def default_foreign_key_field
  @default_foreign_key_field ||= "#{name.to_s.singularize}#{FOREIGN_KEY_SUFFIX}"
end

#default_primary_key (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 197

def default_primary_key
  PRIMARY_KEY_DEFAULT
end

#determine_inverses(other) (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 245

def determine_inverses(other)
  matches = (other || relation_class).relations.values.select do |rel|
    relation_complements.include?(rel.class) &&
        rel.relation_class_name == inverse_class_name

  end
  if matches.size > 1
    raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
  end
  matches.collect { |m| m.name } unless matches.blank?
end

#foreign_keyString

Get the foreign key field for saving the association reference.

Returns:

  • (String)

    The foreign key field for saving the association reference.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 102

def foreign_key
  @foreign_key ||= @options[:foreign_key] ? @options[:foreign_key].to_s :
                     default_foreign_key_field
end

#index_spec (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 193

def index_spec
  { key => 1 }
end

#inverse_foreign_keyString

Get the foreign key field on the inverse.

Returns:

  • (String)

    The foreign key field for saving the association reference on the inverse side.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 118

def inverse_foreign_key
  if @options.key?(:inverse_foreign_key)
    @options[:inverse_foreign_key]
  elsif @options.key?(:inverse_of)
    inverse_of ? "#{inverse_of.to_s.singularize}#{FOREIGN_KEY_SUFFIX}" : nil
  elsif inv = inverse_association&.foreign_key
    inv
  else
    "#{inverse_class_name.demodulize.underscore}#{FOREIGN_KEY_SUFFIX}"
  end
end

#inverse_foreign_key_setterString

Get the foreign key setter on the inverse.

Returns:

  • (String)

    The foreign key setter for saving the association reference on the inverse side.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 144

def inverse_foreign_key_setter
  @inverse_foreign_key_setter ||= "#{inverse_foreign_key}=" if inverse_foreign_key
end

#nested_builder(attributes, options) ⇒ Association::Nested::One

The nested builder object.

Parameters:

  • attributes (Hash)

    The attributes to use to build the association object.

  • options (Hash)

    The options for the association.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 154

def nested_builder(attributes, options)
  Nested::Many.new(self, attributes, options)
end

#path(document) ⇒ Root

Get the path calculator for the supplied document.

Examples:

Get the path calculator.

association.path(document)

Parameters:

  • document (Document)

    The document to calculate on.

Returns:

  • (Root)

    The root atomic path calculator.

[ GitHub ]

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

def path(document)
  Mongoid::Atomic::Paths::Root.new(document)
end

#query_criteria(id_list) (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 265

def query_criteria(id_list)
  crit = relation_class.criteria
  crit = if id_list
    crit = crit.apply_scope(scope)
    crit.all_of(primary_key => { "$in" => id_list })
  else
    crit.none
  end
  with_ordering(crit)
end

#relationAssociation::HasAndBelongsToMany::Proxy

Get the association proxy class for this association type.

Returns:

  • (Association::HasAndBelongsToMany::Proxy)

    The proxy class.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 95

def relation
  Proxy
end

#relation_complementsArray<Mongoid::Association::Relatable>

The list of association complements.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 58

def relation_complements
  @relation_complements ||= [ self.class ].freeze
end

#scopeProc | Symbol | nil

Get the scope to be applied when querying the association.

Returns:

  • (Proc | Symbol | nil)

    The association scope, if any.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 173

def scope
  @options[:scope]
end

#setup!self

Setup the instance methods, fields, etc. on the association owning class.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 65

def setup!
  setup_instance_methods!
  self
end

#setup_instance_methods! (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 179

def setup_instance_methods!
  define_getter!
  define_setter!
  define_dependency!
  define_existence_check!
  define_autosaver!
  define_counter_cache_callbacks!
  create_foreign_key_field!
  setup_index!
  setup_syncing!
  @owner_class.validates_associated(name) if validate?
  self
end

#setup_syncing! (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 205

def setup_syncing!
  unless forced_nil_inverse?
    synced_save
    synced_destroy
  end
end

#synced_destroy (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 212

def synced_destroy
  assoc = self
  inverse_class.set_callback(
      :destroy,
      :after
  ) do |doc|
    doc.remove_inverse_keys(assoc)
  end
end

#synced_save (private)

[ GitHub ]

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

def synced_save
  assoc = self
  inverse_class.set_callback(
      :persist_parent,
      :after,
      if: ->(doc){ doc._syncable?(assoc) }
  ) do |doc|
    doc.update_inverse_keys(assoc)
  end
end

#validation_defaultfalse

The default for validation the association object.

Returns:

  • (false)

    Always false.

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 78

def validation_default; true; end

#with_ordering(criteria) (private)

[ GitHub ]

  
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many.rb', line 257

def with_ordering(criteria)
  if order
    criteria.order_by(order)
  else
    criteria
  end
end