Class: ActiveRecord::Reflection::AssociationReflection

Inherits:
MacroReflection show all
Defined in:
lib/active_record/reflection.rb

Overview

Holds all the meta-data about an association as it was specified in the Active Record class.

Constant Summary collapse

VALID_AUTOMATIC_INVERSE_MACROS =
[:has_many, :has_one, :belongs_to]
INVALID_AUTOMATIC_INVERSE_OPTIONS =
[:conditions, :through, :polymorphic, :foreign_key]

Instance Attribute Summary collapse

Attributes inherited from MacroReflection

#active_record, #name, #options, #plural_name, #scope

Instance Method Summary collapse

Methods inherited from MacroReflection

#==, #autosave=

Methods inherited from AbstractReflection

#build_association, #check_validity_of_inverse!, #class_name, #inverse_of, #join_keys, #primary_key_type, #quoted_table_name, #source_macro, #table_name

Constructor Details

#initialize(name, scope, options, active_record) ⇒ AssociationReflection

Returns a new instance of AssociationReflection.



301
302
303
304
305
306
307
308
309
# File 'lib/active_record/reflection.rb', line 301

def initialize(name, scope, options, active_record)
  super
  @automatic_inverse_of = nil
  @type         = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
  @foreign_type = options[:foreign_type] || "#{name}_type"
  @constructable = calculate_constructable(macro, options)
  @association_scope_cache = {}
  @scope_lock = Mutex.new
end

Instance Attribute Details

#foreign_typeObject (readonly)

Returns the value of attribute foreign_type.



298
299
300
# File 'lib/active_record/reflection.rb', line 298

def foreign_type
  @foreign_type
end

#parent_reflectionObject

:name, Reflection


299
300
301
# File 'lib/active_record/reflection.rb', line 299

def parent_reflection
  @parent_reflection
end

#typeObject (readonly)

Returns the value of attribute type.



298
299
300
# File 'lib/active_record/reflection.rb', line 298

def type
  @type
end

Instance Method Details

#active_record_primary_keyObject



342
343
344
# File 'lib/active_record/reflection.rb', line 342

def active_record_primary_key
  @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
end

#association_classObject



447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/active_record/reflection.rb', line 447

def association_class
  case macro
  when :belongs_to
    if polymorphic?
      Associations::BelongsToPolymorphicAssociation
    else
      Associations::BelongsToAssociation
    end
  when :has_many
    if options[:through]
      Associations::HasManyThroughAssociation
    else
      Associations::HasManyAssociation
    end
  when :has_one
    if options[:through]
      Associations::HasOneThroughAssociation
    else
      Associations::HasOneAssociation
    end
  end
end

#association_foreign_keyObject



333
334
335
# File 'lib/active_record/reflection.rb', line 333

def association_foreign_key
  @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
end

#association_primary_key(klass = nil) ⇒ Object

klass option is necessary to support loading polymorphic associations



338
339
340
# File 'lib/active_record/reflection.rb', line 338

def association_primary_key(klass = nil)
  options[:primary_key] || primary_key(klass || self.klass)
end

#association_scope_cache(conn, owner) ⇒ Object



311
312
313
314
315
316
317
318
319
# File 'lib/active_record/reflection.rb', line 311

def association_scope_cache(conn, owner)
  key = conn.prepared_statements
  if polymorphic?
    key = [key, owner._read_attribute(@foreign_type)]
  end
  @association_scope_cache[key] ||= @scope_lock.synchronize {
    @association_scope_cache[key] ||= yield
  }
end

#belongs_to?Boolean

Returns true if self is a belongs_to reflection.

Returns:

  • (Boolean)


442
# File 'lib/active_record/reflection.rb', line 442

def belongs_to?; false; end

#chainObject

A chain of reflections from this one back to the owner. For more see the explanation in ThroughReflection.



388
389
390
# File 'lib/active_record/reflection.rb', line 388

def chain
  [self]
end

#check_preloadable!Object Also known as: check_eager_loadable!



358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/active_record/reflection.rb', line 358

def check_preloadable!
  return unless scope

  if scope.arity > 0
    ActiveSupport::Deprecation.warn(<<-MSG.squish)
      The association scope '#{name}' is instance dependent (the scope
      block takes an argument). Preloading happens before the individual
      instances are created. This means that there is no instance being
      passed to the association scope. This will most likely result in
      broken or incorrect behavior. Joining, Preloading and eager loading
      of these associations is deprecated and will be removed in the future.
    MSG
  end
end

#check_validity!Object



354
355
356
# File 'lib/active_record/reflection.rb', line 354

def check_validity!
  check_validity_of_inverse!
end

#collection?Boolean

Returns whether or not this association reflection is for a collection association. Returns true if the macro is either has_many or has_and_belongs_to_many, false otherwise.

Returns:

  • (Boolean)


424
425
426
# File 'lib/active_record/reflection.rb', line 424

def collection?
  false
end

#compute_class(name) ⇒ Object



294
295
296
# File 'lib/active_record/reflection.rb', line 294

def compute_class(name)
  active_record.send(:compute_type, name)
end

#constructable?Boolean

:nodoc:

Returns:

  • (Boolean)


321
322
323
# File 'lib/active_record/reflection.rb', line 321

def constructable? # :nodoc:
  @constructable
end

#counter_cache_columnObject



346
347
348
349
350
351
352
# File 'lib/active_record/reflection.rb', line 346

def counter_cache_column
  if options[:counter_cache] == true
    "#{active_record.name.demodulize.underscore.pluralize}_count"
  elsif options[:counter_cache]
    options[:counter_cache].to_s
  end
end

#foreign_keyObject



329
330
331
# File 'lib/active_record/reflection.rb', line 329

def foreign_key
  @foreign_key ||= options[:foreign_key] || derive_foreign_key.freeze
end

#has_inverse?Boolean

Returns:

  • (Boolean)


402
403
404
# File 'lib/active_record/reflection.rb', line 402

def has_inverse?
  inverse_name
end

#has_one?Boolean

Returns true if self is a has_one reflection.

Returns:

  • (Boolean)


445
# File 'lib/active_record/reflection.rb', line 445

def has_one?; false; end

#join_id_for(owner) ⇒ Object

:nodoc:



374
375
376
# File 'lib/active_record/reflection.rb', line 374

def join_id_for(owner) # :nodoc:
  owner[active_record_primary_key]
end

#join_tableObject



325
326
327
# File 'lib/active_record/reflection.rb', line 325

def join_table
  @join_table ||= options[:join_table] || derive_join_table
end

#klassObject

Returns the target association’s class.

class Author < ActiveRecord::Base
  has_many :books
end

Author.reflect_on_association(:books).klass
# => Book

Note: Do not call klass.new or klass.create to instantiate a new association object. Use build_association or create_association instead. This allows plugins to hook into association object creation.



290
291
292
# File 'lib/active_record/reflection.rb', line 290

def klass
  @klass ||= compute_class(class_name)
end

#macroObject

Returns the macro type.

has_many :clients returns :has_many

Raises:

  • (NotImplementedError)


419
# File 'lib/active_record/reflection.rb', line 419

def macro; raise NotImplementedError; end

#nested?Boolean

Returns:

  • (Boolean)


392
393
394
# File 'lib/active_record/reflection.rb', line 392

def nested?
  false
end

#polymorphic?Boolean

Returns:

  • (Boolean)


470
471
472
# File 'lib/active_record/reflection.rb', line 470

def polymorphic?
  options[:polymorphic]
end

#polymorphic_inverse_of(associated_class) ⇒ Object



406
407
408
409
410
411
412
413
414
# File 'lib/active_record/reflection.rb', line 406

def polymorphic_inverse_of(associated_class)
  if has_inverse?
    if inverse_relationship = associated_class._reflect_on_association(options[:inverse_of])
      inverse_relationship
    else
      raise InverseOfAssociationNotFoundError.new(self, associated_class)
    end
  end
end

#scope_chainObject

An array of arrays of scopes. Each item in the outside array corresponds to a reflection in the #chain.



398
399
400
# File 'lib/active_record/reflection.rb', line 398

def scope_chain
  scope ? [[scope]] : [[]]
end

#source_reflectionObject



382
383
384
# File 'lib/active_record/reflection.rb', line 382

def source_reflection
  self
end

#through_reflectionObject



378
379
380
# File 'lib/active_record/reflection.rb', line 378

def through_reflection
  nil
end

#validate?Boolean

Returns whether or not the association should be validated as part of the parent’s validation.

Unless you explicitly disable validation with validate: false, validation will take place when:

  • you explicitly enable validation; validate: true

  • you use autosave; autosave: true

  • the association is a has_many association

Returns:

  • (Boolean)


437
438
439
# File 'lib/active_record/reflection.rb', line 437

def validate?
  !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || collection?)
end