Module: Mongoid::Association::Relatable

Overview

This module provides behaviors shared between Association types.

Constant Summary collapse

SHARED_OPTIONS =

The options shared between all association types.

i[
  class_name
  inverse_of
  validate
  extend
].freeze
PRIMARY_KEY_DEFAULT =

The primary key default.

'_id'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Options

#as, #autobuilding?, #autosave, #cascading_callbacks?, #counter_cached?, #cyclic?, #dependent, #fallback, #fallback?, #forced_nil_inverse?, #indexed?, #inverse_of, #order, #polymorphic?, #primary_key, #store_as, #touch_field, #touchable?, #type

Methods included from Constrainable

#convert_to_foreign_key

Instance Attribute Details

#nameSymbol (readonly)

The name of the association.



31
32
33
# File 'lib/mongoid/association/relatable.rb', line 31

def name
  @name
end

#optionsHash (readonly)

The options on this association.



36
37
38
# File 'lib/mongoid/association/relatable.rb', line 36

def options
  @options
end

#owner_classClass (readonly)

The class that owns this association.



41
42
43
# File 'lib/mongoid/association/relatable.rb', line 41

def owner_class
  @owner_class
end

#parent_inclusionsArray<String>

The associations above this one in the inclusion tree.



336
337
338
# File 'lib/mongoid/association/relatable.rb', line 336

def parent_inclusions
  @parent_inclusions ||= []
end

Instance Method Details

#==(other) ⇒ Object

Compare this association to another.



65
66
67
68
69
70
# File 'lib/mongoid/association/relatable.rb', line 65

def ==(other)
  relation_class_name == other.relation_class_name &&
    inverse_class_name == other.inverse_class_name &&
    name == other.name &&
    options == other.options
end

#bindable?(_doc) ⇒ true | false

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



96
97
98
# File 'lib/mongoid/association/relatable.rb', line 96

def bindable?(_doc)
  false
end

#counter_cache_column_nameString

Get the counter cache column name.



292
293
294
295
296
297
298
299
# File 'lib/mongoid/association/relatable.rb', line 292

def counter_cache_column_name
  @counter_cache_column_name ||= if @options[:counter_cache].is_a?(String) ||
                                    @options[:counter_cache].is_a?(Symbol)
                                   @options[:counter_cache]
                                 else
                                   "#{inverse || inverse_class_name.demodulize.underscore.pluralize}_count"
                                 end
end

#create_relation(owner, target) ⇒ Proxy

Create an association proxy object using the owner and target.



278
279
280
# File 'lib/mongoid/association/relatable.rb', line 278

def create_relation(owner, target)
  relation.new(owner, target, self)
end

#destructive?true | false

Whether the dependent method is destructive.



285
286
287
# File 'lib/mongoid/association/relatable.rb', line 285

def destructive?
  @destructive ||= !!(dependent && i[delete_all destroy].include?(dependent))
end

#extensionModule

Get the extension.



304
305
306
# File 'lib/mongoid/association/relatable.rb', line 304

def extension
  @extension ||= @options[:extend]
end

#foreign_key_checkString

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

Examples:

Get the foreign key check method.

association.foreign_key_check


267
268
269
# File 'lib/mongoid/association/relatable.rb', line 267

def foreign_key_check
  @foreign_key_check ||= "#{foreign_key}_previously_changed?" if stores_foreign_key? && foreign_key
end

#foreign_key_setterString

The name of the foreign key setter method.



237
238
239
240
241
# File 'lib/mongoid/association/relatable.rb', line 237

def foreign_key_setter
  # NOTE: You can't check if this association stores foreign key
  # See HasOne and HasMany binding, they referenced foreign_key_setter
  @foreign_key_setter ||= "#{foreign_key}=" if foreign_key
end

#get_callbacks(callback_type) ⇒ Array<Proc | Symbol>

Get the callbacks for a given type.



78
79
80
# File 'lib/mongoid/association/relatable.rb', line 78

def get_callbacks(callback_type)
  Array(options[callback_type])
end

#in_to?true | false

Is this association an embedded_in or belongs_to association?



358
359
360
# File 'lib/mongoid/association/relatable.rb', line 358

def in_to?
  [ Referenced::BelongsTo, Embedded::EmbeddedIn ].any? { |a| is_a?(a) }
end

#initialize(_class, name, opts = {}, &block) ⇒ Object

Initialize the Association.



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/mongoid/association/relatable.rb', line 49

def initialize(_class, name, opts = {}, &block)
  @owner_class = _class
  @name = name
  @options = opts
  @extension = nil

  @module_path = _class.name ? _class.name.split('::')[0..-2].join('::') : ''
  @module_path << '::' unless @module_path.empty?

  create_extension!(&block)
  validate!
end

#inverse(other = nil) ⇒ Symbol

Get the inverse name.



311
312
313
314
# File 'lib/mongoid/association/relatable.rb', line 311

def inverse(other = nil)
  candidates = inverses(other)
  candidates.detect { |c| c } if candidates
end

#inverse_association(other = nil) ⇒ Mongoid::Association::Relatable

Get the inverse's association metadata.



123
124
125
# File 'lib/mongoid/association/relatable.rb', line 123

def inverse_association(other = nil)
  (other || relation_class).relations[inverse(other)]
end

#inverse_classString Also known as: inverse_klass

The class of the object owning this association.



207
208
209
# File 'lib/mongoid/association/relatable.rb', line 207

def inverse_class
  @owner_class
end

#inverse_class_nameString

The class name of the object owning this association.



200
201
202
# File 'lib/mongoid/association/relatable.rb', line 200

def inverse_class_name
  @inverse_class_name ||= @owner_class.name
end

#inverse_setter(other = nil) ⇒ String

The name of the inverse setter method.



230
231
232
# File 'lib/mongoid/association/relatable.rb', line 230

def inverse_setter(other = nil)
  @inverse_setter ||= "#{inverses(other).first}=" unless inverses(other).blank?
end

#inverse_typenil

Get the inverse type.



130
# File 'lib/mongoid/association/relatable.rb', line 130

def inverse_type; end

#inverse_type_setterString

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

Examples:

Get the inverse type setter.

association.inverse_type_setter


257
258
259
# File 'lib/mongoid/association/relatable.rb', line 257

def inverse_type_setter
  @inverse_type_setter ||= "#{inverse_type}=" if inverse_type
end

#inverses(other = nil) ⇒ Array<Symbol>

Get the inverse names.



106
107
108
109
110
111
112
113
114
115
# File 'lib/mongoid/association/relatable.rb', line 106

def inverses(other = nil)
  return [ inverse_of ] if inverse_of
  return [] if @options.key?(:inverse_of) && !inverse_of

  if polymorphic?
    polymorphic_inverses(other)
  else
    determine_inverses(other)
  end
end

#keySymbol | String

The foreign key field if this association stores a foreign key. Otherwise, the primary key.



216
217
218
# File 'lib/mongoid/association/relatable.rb', line 216

def key
  stores_foreign_key? ? foreign_key : primary_key
end

#many?true | false

Is this association an embeds_many or has_many association?



343
344
345
# File 'lib/mongoid/association/relatable.rb', line 343

def many?
  [ Referenced::HasMany, Embedded::EmbedsMany ].any? { |a| is_a?(a) }
end

#many_to_many?true | false

Is this association a many-to-many association? Such an association stores its foreign keys as an array on the document itself.



367
368
369
# File 'lib/mongoid/association/relatable.rb', line 367

def many_to_many?
  is_a?(Referenced::HasAndBelongsToMany)
end

#one?true | false

Is this association an embeds_one or has_one association?



350
351
352
# File 'lib/mongoid/association/relatable.rb', line 350

def one?
  [ Referenced::HasOne, Embedded::EmbedsOne ].any? { |a| is_a?(a) }
end

#path(document) ⇒ Mongoid::Atomic::Paths::Root

The atomic path for this association.



246
247
248
# File 'lib/mongoid/association/relatable.rb', line 246

def path(document)
  relation.path(document)
end

#relation_classString Also known as: klass

The class of the association object(s).

This method returns the class instance corresponding to relation_class_name, resolved relative to the host document class.

If the class does not exist, this method raises NameError. This can happen because the target class has not yet been defined. Note that polymorphic associations generally do not have a well defined target class because the target class can change from one object to another, and calling this method on a polymorphic association will generally fail with a NameError or produce misleading results (if a class does happen to be defined with the same name as the association name).



172
173
174
175
176
177
# File 'lib/mongoid/association/relatable.rb', line 172

def relation_class
  @klass ||= begin
    cls_name = @options[:class_name] || ActiveSupport::Inflector.classify(name)
    resolve_name(inverse_class, cls_name)
  end
end

#relation_class_nameString Also known as: class_name

Note:

The return value of this method should not be used to determine whether two associations have the same target class, because the return value is not always a fully qualified class name. To compare classes, retrieve the class instance of the association target using the relation_class method.

The class name, possibly unqualified or

prefixed, of the association

object(s).

This method returns the class name as it is used in the association definition. If :class_name option is given in the association, the exact value of that option is returned here. If :class_name option is not given, the name of the class is calculated from association name but is not resolved to the actual class.

The class name returned by this method may not correspond to a defined class, either because the corresponding class has not been loaded yet, or because the association references a non-existent class altogether. To obtain the association class, use relation_class method.



153
154
155
# File 'lib/mongoid/association/relatable.rb', line 153

def relation_class_name
  @class_name ||= @options[:class_name] || ActiveSupport::Inflector.classify(name)
end

#setterString

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



223
224
225
# File 'lib/mongoid/association/relatable.rb', line 223

def setter
  @setter ||= "#{name}="
end

#try_relation_classClass | nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The class of the association target, or nil when the named class is not defined.

An association may name a class that never gets defined. The association is then unusable, but its owner still has to be. Callers that walk every association of every model, rather than following the one the application asked for, use this instead of relation_class.



191
192
193
194
195
# File 'lib/mongoid/association/relatable.rb', line 191

def try_relation_class
  relation_class
rescue NameError
  nil
end

#type_setterString

Note:

Only relevant for polymorphic associations that take the :as option.

Get the type setter.



86
87
88
# File 'lib/mongoid/association/relatable.rb', line 86

def type_setter
  @type_setter ||= "#{type}=" if type
end

#validate?true | false

Whether the associated object(s) should be validated.



320
321
322
323
324
325
326
# File 'lib/mongoid/association/relatable.rb', line 320

def validate?
  @validate ||= if @options[:validate].nil?
                  validation_default
                else
                  !!@options[:validate]
                end
end