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, #class_name, #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.



277
278
279
280
281
282
283
284
285
# File 'lib/active_record/reflection.rb', line 277

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.



274
275
276
# File 'lib/active_record/reflection.rb', line 274

def foreign_type
  @foreign_type
end

#parent_reflectionObject

:name, Reflection


275
276
277
# File 'lib/active_record/reflection.rb', line 275

def parent_reflection
  @parent_reflection
end

#typeObject (readonly)

Returns the value of attribute type.



274
275
276
# File 'lib/active_record/reflection.rb', line 274

def type
  @type
end

Instance Method Details

#active_record_primary_keyObject



318
319
320
# File 'lib/active_record/reflection.rb', line 318

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

#association_classObject



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'lib/active_record/reflection.rb', line 437

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



309
310
311
# File 'lib/active_record/reflection.rb', line 309

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



314
315
316
# File 'lib/active_record/reflection.rb', line 314

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

#association_scope_cache(conn, owner) ⇒ Object



287
288
289
290
291
292
293
294
295
# File 'lib/active_record/reflection.rb', line 287

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)


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

def belongs_to?; false; end

#chainObject

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



372
373
374
# File 'lib/active_record/reflection.rb', line 372

def chain
  [self]
end

#check_preloadable!Object Also known as: check_eager_loadable!



342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/active_record/reflection.rb', line 342

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



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

def check_validity!
  check_validity_of_inverse!
end

#check_validity_of_inverse!Object



334
335
336
337
338
339
340
# File 'lib/active_record/reflection.rb', line 334

def check_validity_of_inverse!
  unless polymorphic?
    if has_inverse? && inverse_of.nil?
      raise InverseOfAssociationNotFoundError.new(self)
    end
  end
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)


414
415
416
# File 'lib/active_record/reflection.rb', line 414

def collection?
  false
end

#compute_class(name) ⇒ Object



270
271
272
# File 'lib/active_record/reflection.rb', line 270

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

#constructable?Boolean

:nodoc:

Returns:

  • (Boolean)


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

def constructable? # :nodoc:
  @constructable
end

#counter_cache_columnObject



322
323
324
325
326
327
328
# File 'lib/active_record/reflection.rb', line 322

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



305
306
307
# File 'lib/active_record/reflection.rb', line 305

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

#has_inverse?Boolean

Returns:

  • (Boolean)


386
387
388
# File 'lib/active_record/reflection.rb', line 386

def has_inverse?
  inverse_name
end

#has_one?Boolean

Returns true if self is a has_one reflection.

Returns:

  • (Boolean)


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

def has_one?; false; end

#inverse_ofObject



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

def inverse_of
  return unless inverse_name

  @inverse_of ||= klass._reflect_on_association inverse_name
end

#join_id_for(owner) ⇒ Object

:nodoc:



358
359
360
# File 'lib/active_record/reflection.rb', line 358

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

#join_tableObject



301
302
303
# File 'lib/active_record/reflection.rb', line 301

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.



266
267
268
# File 'lib/active_record/reflection.rb', line 266

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

#macroObject

Returns the macro type.

has_many :clients returns :has_many

Raises:

  • (NotImplementedError)


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

def macro; raise NotImplementedError; end

#nested?Boolean

Returns:

  • (Boolean)


376
377
378
# File 'lib/active_record/reflection.rb', line 376

def nested?
  false
end

#polymorphic?Boolean

Returns:

  • (Boolean)


460
461
462
# File 'lib/active_record/reflection.rb', line 460

def polymorphic?
  options[:polymorphic]
end

#polymorphic_inverse_of(associated_class) ⇒ Object



396
397
398
399
400
401
402
403
404
# File 'lib/active_record/reflection.rb', line 396

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.



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

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

#source_reflectionObject



366
367
368
# File 'lib/active_record/reflection.rb', line 366

def source_reflection
  self
end

#through_reflectionObject



362
363
364
# File 'lib/active_record/reflection.rb', line 362

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)


427
428
429
# File 'lib/active_record/reflection.rb', line 427

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