Class: ActiveRecord::Reflection::ThroughReflection
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
AbstractReflection
|
|
Instance Chain:
self,
AbstractReflection
|
|
Inherits: |
ActiveRecord::Reflection::AbstractReflection
|
Defined in: | activerecord/lib/active_record/reflection.rb |
Overview
Holds all the metadata about a :through
association as it was specified in the Active Record class.
Class Method Summary
Instance Attribute Summary
- #active_record_primary_key readonly
- #association_foreign_key readonly
- #foreign_key readonly
- #foreign_type readonly
- #has_scope? ⇒ Boolean readonly
- #join_foreign_key readonly
- #join_id_for readonly
-
#nested? ⇒ Boolean
readonly
A through association is nested if there would be more than one join table.
- #through_reflection? ⇒ Boolean readonly
- #type readonly
- #delegate_reflection readonly private
AbstractReflection
- Inherited
#counter_must_be_updated_by_has_many?, | |
#has_active_cached_counter? | Returns whether this association has a counter cache and its column values were backfilled (and so it is used internally by methods like |
#has_cached_counter? | Returns whether this association has a counter cache. |
#inverse_updates_counter_cache? | |
#inverse_updates_counter_in_memory?, #strict_loading?, #through_reflection? |
Instance Method Summary
- #add_as_polymorphic_through(reflection, seed)
- #add_as_source(seed)
- #add_as_through(seed)
-
#association_primary_key(klass = nil)
We want to use the klass from this reflection, rather than just delegate straight to the source_reflection, because the source_reflection may be polymorphic.
- #check_validity!
-
#clear_association_scope_cache
This is for clearing cache on the reflection.
-
#collect_join_chain
Returns an array of reflections which are involved in this association.
- #constraints
- #join_primary_key(klass = self.klass)
- #join_scopes(table, predicate_builder = nil, klass = self.klass, record = nil)
- #klass
- #scopes
- #source_options
-
#source_reflection
Returns the source of the through reflection.
- #source_reflection_name
-
#source_reflection_names
Gets an array of possible
:through
source reflection names in both singular and plural form. - #through_options
-
#through_reflection
readonly
Returns the
AssociationReflection
object specified in the:through
option of a HasManyThrough or HasOneThrough association. -
#actual_source_reflection
protected
FIXME: this is a horrible name.
- #collect_join_reflections(seed) private
- #derive_class_name private
- #inverse_name private
AbstractReflection
- Inherited
#alias_candidate, | |
#build_association | Returns a new, unsaved instance of the associated class. |
#build_scope, #chain, #check_validity_of_inverse!, | |
#class_name | Returns the class name for the macro. |
#constraints, #counter_cache_column, #inverse_of, | |
#inverse_which_updates_counter_cache | We need to avoid the following situation: |
#join_scope, #join_scopes, #klass_join_scope, | |
#scopes | Returns a list of scopes that should be applied for this |
#strict_loading_violation_message, #table_name, | |
#actual_source_reflection | FIXME: this is a horrible name. |
#ensure_option_not_given_as_class!, #primary_key |
Constructor Details
.new(delegate_reflection) ⇒ ThroughReflection
# File 'activerecord/lib/active_record/reflection.rb', line 976
def initialize(delegate_reflection) super() @delegate_reflection = delegate_reflection @klass = delegate_reflection. [:anonymous_class] @source_reflection_name = delegate_reflection. [:source] ensure_option_not_given_as_class!(:source_type) end
Instance Attribute Details
#active_record_primary_key (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
#association_foreign_key (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
#delegate_reflection (readonly, private)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1204
attr_reader :delegate_reflection
#foreign_key (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
#foreign_type (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
#has_scope? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/reflection.rb', line 1069
def has_scope? scope || [:source_type] || source_reflection.has_scope? || through_reflection.has_scope? end
#join_foreign_key (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
#join_id_for (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
#nested? ⇒ Boolean
(readonly)
A through association is nested if there would be more than one join table
# File 'activerecord/lib/active_record/reflection.rb', line 1076
def nested? source_reflection.through_reflection? || through_reflection.through_reflection? end
#through_reflection? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/reflection.rb', line 985
def through_reflection? true end
#type (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 973
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type, :active_record_primary_key, :join_foreign_key, to: :source_reflection
Instance Method Details
#actual_source_reflection (protected)
FIXME: this is a horrible name
# File 'activerecord/lib/active_record/reflection.rb', line 1199
def actual_source_reflection # FIXME: this is a horrible name source_reflection.actual_source_reflection end
#add_as_polymorphic_through(reflection, seed)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1190
def add_as_polymorphic_through(reflection, seed) collect_join_reflections(seed + [PolymorphicReflection.new(self, reflection)]) end
#add_as_source(seed)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1186
def add_as_source(seed) collect_join_reflections seed end
#add_as_through(seed)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1194
def add_as_through(seed) collect_join_reflections(seed + [self]) end
#association_primary_key(klass = nil)
We want to use the klass from this reflection, rather than just delegate straight to the source_reflection, because the source_reflection may be polymorphic. We still need to respect the source_reflection’s :primary_key
option, though.
# File 'activerecord/lib/active_record/reflection.rb', line 1083
def association_primary_key(klass = nil) # Get the "actual" source reflection if the immediate source reflection has a # source reflection itself if primary_key = actual_source_reflection. [:primary_key] @association_primary_key ||= -primary_key.to_s else primary_key(klass || self.klass) end end
#check_validity!
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1140
def check_validity! if through_reflection.nil? raise HasManyThroughAssociationNotFoundError.new(active_record, self) end if through_reflection.polymorphic? if has_one? raise HasOneAssociationPolymorphicThroughError.new(active_record.name, self) else raise HasManyThroughAssociationPolymorphicThroughError.new(active_record.name, self) end end if source_reflection.nil? raise HasManyThroughSourceAssociationNotFoundError.new(self) end if [:source_type] && !source_reflection.polymorphic? raise HasManyThroughAssociationPointlessSourceTypeError.new(active_record.name, self, source_reflection) end if source_reflection.polymorphic? && [:source_type].nil? raise HasManyThroughAssociationPolymorphicSourceError.new(active_record.name, self, source_reflection) end if has_one? && through_reflection.collection? raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection) end if parent_reflection.nil? reflections = active_record.normalized_reflections.keys if reflections.index(through_reflection.name) > reflections.index(name) raise HasManyThroughOrderError.new(active_record.name, self, through_reflection) end end check_validity_of_inverse! end
#clear_association_scope_cache
This is for clearing cache on the reflection. Useful for tests that need to compare SQL queries on associations.
# File 'activerecord/lib/active_record/reflection.rb', line 1055
def clear_association_scope_cache # :nodoc: delegate_reflection.clear_association_scope_cache source_reflection.clear_association_scope_cache through_reflection.clear_association_scope_cache end
#collect_join_chain
Returns an array of reflections which are involved in this association. Each item in the array corresponds to a table which will be part of the query for this association.
The chain is built by recursively calling #chain
on the source reflection and the through reflection. The base case for the recursion is a normal association, which just returns
- self
-
as its
#chain
.
class Post < ActiveRecord::Base
has_many :taggings
has_many :, through: :taggings
end
= Post.reflect_on_association(: )
.chain
# => [<ActiveRecord::Reflection::ThroughReflection: @delegate_reflection=#<ActiveRecord::Reflection::HasManyReflection: @name=:tags...>,
<ActiveRecord::Reflection::HasManyReflection: @name=:taggings, @options={}, @active_record=Post>]
# File 'activerecord/lib/active_record/reflection.rb', line 1049
def collect_join_chain collect_join_reflections [self] end
#collect_join_reflections(seed) (private)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1206
def collect_join_reflections(seed) a = source_reflection.add_as_source seed if [:source_type] through_reflection.add_as_polymorphic_through self, a else through_reflection.add_as_through a end end
#constraints
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1180
def constraints scope_chain = source_reflection.constraints scope_chain << scope if scope scope_chain end
#derive_class_name (private)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1217
def derive_class_name # get the class_name of the belongs_to association of the through reflection [:source_type] || source_reflection.class_name end
#inverse_name (private)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1215
def inverse_name; delegate_reflection.send(:inverse_name); end
#join_primary_key(klass = self.klass)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1093
def join_primary_key(klass = self.klass) source_reflection.join_primary_key(klass) end
#join_scopes(table, predicate_builder = nil, klass = self.klass, record = nil)
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1065
def join_scopes(table, predicate_builder = nil, klass = self.klass, record = nil) # :nodoc: source_reflection.join_scopes(table, predicate_builder, klass, record) + super end
#klass
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 989
def klass @klass ||= delegate_reflection._klass(class_name) end
#scopes
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1061
def scopes source_reflection.scopes + super end
#source_options
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1132
def source_reflection. end
#source_reflection
Returns the source of the through reflection. It checks both a singularized and pluralized form for :belongs_to
or :has_many
.
class Post < ActiveRecord::Base
has_many :taggings
has_many :, through: :taggings
end
class Tagging < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
= Post.reflect_on_association(: )
.source_reflection
# => <ActiveRecord::Reflection::BelongsToReflection: @name=:tag, @active_record=Tagging, @plural_name="tags">
# File 'activerecord/lib/active_record/reflection.rb', line 1010
def source_reflection return unless source_reflection_name through_reflection.klass._reflect_on_association(source_reflection_name) end
#source_reflection_name
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1112
def source_reflection_name # :nodoc: @source_reflection_name ||= begin names = [name.to_s.singularize, name].collect(&:to_sym).uniq names = names.find_all { |n| through_reflection.klass._reflect_on_association(n) } if names.length > 1 raise AmbiguousSourceReflectionForThroughAssociation.new( active_record.name, macro, name, , source_reflection_names ) end names.first end end
#source_reflection_names
Gets an array of possible :through
source reflection names in both singular and plural form.
class Post < ActiveRecord::Base
has_many :taggings
has_many :, through: :taggings
end
= Post.reflect_on_association(: )
.source_reflection_names
# => [:tag, :tags]
# File 'activerecord/lib/active_record/reflection.rb', line 1108
def source_reflection_names [:source] ? [ [:source]] : [name.to_s.singularize, name].uniq end
#through_options
[ GitHub ]# File 'activerecord/lib/active_record/reflection.rb', line 1136
def through_reflection. end
#through_reflection (readonly)
Returns the AssociationReflection
object specified in the :through
option of a HasManyThrough or HasOneThrough association.
class Post < ActiveRecord::Base
has_many :taggings
has_many :, through: :taggings
end
= Post.reflect_on_association(: )
.through_reflection
# => <ActiveRecord::Reflection::HasManyReflection: @name=:taggings, @active_record=Post, @plural_name="taggings">
# File 'activerecord/lib/active_record/reflection.rb', line 1028
def through_reflection active_record._reflect_on_association( [:through]) end