class ActiveRecord::Reflection::AssociationReflection
:nodoc:
Active Record class.
Holds all the metadata about an association as it was specified in the
def active_record_primary_key
def active_record_primary_key @active_record_primary_key ||= -(options[:primary_key]&.to_s || primary_key(active_record)) end
def add_as_polymorphic_through(reflection, seed)
def add_as_polymorphic_through(reflection, seed) seed + [PolymorphicReflection.new(self, reflection)] end
def add_as_source(seed)
def add_as_source(seed) seed end
def add_as_through(seed)
def add_as_through(seed) seed + [self] end
def association_class; raise NotImplementedError; end
def association_class; raise NotImplementedError; end
def association_foreign_key
def association_foreign_key @association_foreign_key ||= -(options[:association_foreign_key]&.to_s || class_name.foreign_key) end
def association_primary_key(klass = nil)
def association_primary_key(klass = nil) primary_key(klass || self.klass) end
def association_scope_cache(klass, owner, &block)
def association_scope_cache(klass, owner, &block) key = self if polymorphic? key = [key, owner._read_attribute(@foreign_type)] end klass.cached_find_by_statement(key, &block) end
def automatic_inverse_of
def automatic_inverse_of if can_find_inverse_of_automatically?(self) inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym begin reflection = klass._reflect_on_association(inverse_name) rescue NameError # Give up: we couldn't compute the klass type so we won't be able # to find any associations either. reflection = false end if valid_inverse_reflection?(reflection) inverse_name end end end
def belongs_to?; false; end
def belongs_to?; false; end
def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
Third, we must not have options such as :foreign_key
have has_many, has_one, belongs_to associations.
inverse_of option cannot be set to false. Second, we must
us from being able to guess the inverse automatically. First, the
Checks to see if the reflection doesn't have any options that prevent
def can_find_inverse_of_automatically?(reflection, inverse_reflection = false) reflection.options[:inverse_of] != false && !reflection.options[:through] && !reflection.options[:foreign_key] && scope_allows_automatic_inverse_of?(reflection, inverse_reflection) end
def check_eager_loadable!
def check_eager_loadable! return unless scope unless scope.arity == 0 raise ArgumentError, <<-MSG.squish The association scope '#{name}' is instance dependent (the scope block takes an argument). Eager loading instance dependent scopes is not supported. MSG end end
def check_validity!
def check_validity! check_validity_of_inverse! end
def clear_association_scope_cache # :nodoc:
SQL queries on associations.
This is for clearing cache on the reflection. Useful for tests that need to compare
def clear_association_scope_cache # :nodoc: klass.initialize_find_by_cache end
def collect_join_chain
A chain of reflections from this one back to the owner. For more see the explanation in
def collect_join_chain [self] end
def collection?
association. Returns +true+ if the +macro+ is either +has_many+ or
Returns whether or not this association reflection is for a collection
def collection? false end
def compute_class(name)
Active Record class.
Holds all the metadata about an association as it was specified in the
def compute_class(name) if polymorphic? raise ArgumentError, "Polymorphic associations do not support computing the class." end msg = <<-MSG.squish Rails couldn't find a valid model for #{name} association. Please provide the :class_name option on the association declaration. If :class_name is already provided, make sure it's an ActiveRecord::Base subclass. MSG begin klass = active_record.send(:compute_type, name) unless klass < ActiveRecord::Base raise ArgumentError, msg end klass rescue NameError raise NameError, msg end end
def derive_class_name
def derive_class_name class_name = name.to_s class_name = class_name.singularize if collection? class_name.camelize end
def derive_foreign_key
def derive_foreign_key if belongs_to? "#{name}_id" elsif options[:as] "#{options[:as]}_id" else active_record.model_name.to_s.foreign_key end end
def derive_join_table
def derive_join_table ModelSchema.derive_join_table_name active_record.table_name, klass.table_name end
def extensions
def extensions Array(options[:extend]) end
def foreign_key
def foreign_key @foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key) end
def has_inverse?
def has_inverse? inverse_name end
def has_one?; false; end
def has_one?; false; end
def has_scope?
def has_scope? scope end
def initialize(name, scope, options, active_record)
def initialize(name, scope, options, active_record) super @type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as] @foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic] ensure_option_not_given_as_class!(:class_name) end
def inverse_name
If it cannot find a suitable inverse association name, it returns
Attempts to find the inverse association name automatically.
def inverse_name unless defined?(@inverse_name) @inverse_name = options.fetch(:inverse_of) { automatic_inverse_of } end @inverse_name end
def join_foreign_key
def join_foreign_key active_record_primary_key end
def join_id_for(owner) # :nodoc:
def join_id_for(owner) # :nodoc: owner[join_foreign_key] end
def join_primary_key(klass = nil)
def join_primary_key(klass = nil) foreign_key end
def join_primary_type
def join_primary_type type end
def join_table
def join_table @join_table ||= -(options[:join_table]&.to_s || derive_join_table) end
def macro; raise NotImplementedError; end
Returns the macro type.
def macro; raise NotImplementedError; end
def nested?
def nested? false end
def polymorphic?
def polymorphic? options[:polymorphic] end
def polymorphic_inverse_of(associated_class)
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
def polymorphic_name
def polymorphic_name active_record.polymorphic_name end
def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
config.active_record.automatic_scope_inversing is set to
automatic inverse_of as long as
we would inverse from. Scopes on the reflection itself allow for
inverse_of, since the scope could exclude the owner record
Scopes on the potential inverse reflection prevent automatic
def scope_allows_automatic_inverse_of?(reflection, inverse_reflection) if inverse_reflection !reflection.scope else !reflection.scope || reflection.klass.automatic_scope_inversing end end
def source_reflection
def source_reflection self end
def through_reflection
def through_reflection nil end
def valid_inverse_reflection?(reflection)
make sure that the reflection's active_record name matches up
+automatic_inverse_of+ method is a valid reflection. We must
Checks if the inverse reflection that is returned from the
def valid_inverse_reflection?(reflection) reflection && reflection != self && foreign_key == reflection.foreign_key && klass <= reflection.active_record && can_find_inverse_of_automatically?(reflection, true) end
def validate?
* you use autosave; autosave: true
* you explicitly enable validation; validate: true
validate: false, validation will take place when:
Unless you explicitly disable validation with
the parent's validation.
Returns whether or not the association should be validated as part of
def validate? !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || collection?) end