class Mongoid::Association::Referenced::HasAndBelongsToMany

The HasAndBelongsToMany type association.

@since 7.0

Constants

ASSOCIATION_OPTIONS

The options available for this type of association, in addition to the common ones.

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

@since 7.0

FOREIGN_KEY_FIELD_TYPE

The type of the field holding the foreign key.

@return [ Array ]

@since 7.0

FOREIGN_KEY_SUFFIX

The default foreign key suffix.

@return [ String ] ‘_ids’

@since 7.0

VALID_OPTIONS

The complete list of valid options for this association, including the shared ones.

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

@since 7.0

Public Instance Methods

bindable?(doc) click to toggle source

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

@param [ Document ] doc The document to be bound.

@return [ true, false ] Whether the document can be bound.

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 163
def bindable?(doc)
  forced_nil_inverse? || (!!inverse && doc.fields.keys.include?(foreign_key))
end
criteria(base, id_list = nil) click to toggle source

The criteria used for querying this association.

@return [ Mongoid::Criteria ] The criteria used for querying this association.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 137
def criteria(base, id_list = nil)
  query_criteria(id_list || base.send(foreign_key))
end
embedded?() click to toggle source

Is this association type embedded?

@return [ false ] Always false.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 88
def embedded?; false; end
forced_nil_inverse?() click to toggle source

Are ids only saved on this side of the association?

@return [ true, false ] Whether this association has a forced nil inverse.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 102
def forced_nil_inverse?
  @forced_nil_inverse ||= @options.key?(:inverse_of) && !@options[:inverse_of]
end
foreign_key() click to toggle source

Get the foreign key field for saving the association reference.

@return [ String ] The foreign key field for saving the association reference.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 127
def foreign_key
  @foreign_key ||= @options[:foreign_key] ? @options[:foreign_key].to_s :
                     default_foreign_key_field
end
inverse_foreign_key() click to toggle source

Get the foreign key field on the inverse.

@return [ String ] The foreign key field for saving the association reference

on the inverse side.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 147
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
  else
    "#{inverse_class_name.demodulize.underscore}#{FOREIGN_KEY_SUFFIX}"
  end
end
inverse_foreign_key_setter() click to toggle source

Get the foreign key setter on the inverse.

@return [ String ] The foreign key setter for saving the association reference

on the inverse side.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 173
def inverse_foreign_key_setter
  @inverse_foreign_key_setter ||= "#{inverse_foreign_key}=" if inverse_foreign_key
end
nested_builder(attributes, options) click to toggle source

The nested builder object.

@param [ Hash ] attributes The attributes to use to build the association object. @param [ Hash ] options The options for the association.

@return [ Association::Nested::One ] The Nested Builder object.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 185
def nested_builder(attributes, options)
  Nested::Many.new(self, attributes, options)
end
path(document) click to toggle source

Get the path calculator for the supplied document.

@example Get the path calculator.

association.path(document)

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

@return [ Root ] The root atomic path calculator.

@since 2.1.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 199
def path(document)
  Mongoid::Atomic::Paths::Root.new(document)
end
relation() click to toggle source

Get the association proxy class for this association type.

@return [ Association::HasAndBelongsToMany::Proxy ] The proxy class.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 118
def relation
  Proxy
end
relation_complements() click to toggle source

The list of association complements.

@return [ Array<Association> ] The association complements.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 69
def relation_complements
  @relation_complements ||= [ self.class ].freeze
end
setup!() click to toggle source

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

@return [ self ]

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 78
def setup!
  setup_instance_methods!
  self
end
stores_foreign_key?() click to toggle source

Does this association type store the foreign key?

@return [ true ] Always true.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 111
def stores_foreign_key?; true; end
validation_default() click to toggle source

The default for validation the association object.

@return [ false ] Always false.

@since 7.0

# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 95
def validation_default; true; end

Private Instance Methods

create_foreign_key_field!() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 259
def create_foreign_key_field!
  @owner_class.field(
      foreign_key,
      type: FOREIGN_KEY_FIELD_TYPE,
      identity: true,
      overwrite: true,
      association: self,
      default: nil
  )
end
default_foreign_key_field() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 227
def default_foreign_key_field
  @default_foreign_key_field ||= "#{name.to_s.singularize}#{FOREIGN_KEY_SUFFIX}"
end
default_primary_key() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 223
def default_primary_key
  PRIMARY_KEY_DEFAULT
end
determine_inverses(other) click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 270
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
index_spec() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 219
def index_spec
  { key => 1 }
end
query_criteria(id_list) click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 290
def query_criteria(id_list)
  crit = relation_class.all_of(primary_key => {"$in" => id_list || []})
  with_ordering(crit)
end
setup_instance_methods!() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 205
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!() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 231
def setup_syncing!
  unless forced_nil_inverse?
    synced_save
    synced_destroy
  end
end
synced_destroy() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 238
def synced_destroy
  assoc = self
  inverse_class.set_callback(
      :destroy,
      :after
  ) do |doc|
    doc.remove_inverse_keys(assoc)
  end
end
synced_save() click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 248
def synced_save
  assoc = self
  inverse_class.set_callback(
      :save,
      :after,
      if: ->(doc){ doc._syncable?(assoc) }
  ) do |doc|
    doc.update_inverse_keys(assoc)
  end
end
with_ordering(criteria) click to toggle source
# File lib/mongoid/association/referenced/has_and_belongs_to_many.rb, line 282
def with_ordering(criteria)
  if order
    criteria.order_by(order)
  else
    criteria
  end
end