Class: ActiveRecord::Reflection::ThroughReflection
- Inherits:
-
AbstractReflection
- Object
- AbstractReflection
- ActiveRecord::Reflection::ThroughReflection
- Defined in:
- lib/active_record/reflection.rb
Overview
Holds all the metadata about a :through association as it was specified in the Active Record class.
Instance Method Summary collapse
- #add_as_polymorphic_through(reflection, seed) ⇒ Object
- #add_as_source(seed) ⇒ Object
- #add_as_through(seed) ⇒ Object
-
#association_primary_key(klass = nil) ⇒ Object
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! ⇒ Object
-
#clear_association_scope_cache ⇒ Object
This is for clearing cache on the reflection.
-
#collect_join_chain ⇒ Object
Returns an array of reflections which are involved in this association.
- #constraints ⇒ Object
- #has_scope? ⇒ Boolean
-
#initialize(delegate_reflection) ⇒ ThroughReflection
constructor
A new instance of ThroughReflection.
- #join_primary_key(klass = self.klass) ⇒ Object
-
#join_scopes(table, predicate_builder, klass = self.klass, record = nil) ⇒ Object
:nodoc:.
- #klass ⇒ Object
-
#nested? ⇒ Boolean
A through association is nested if there would be more than one join table.
- #scopes ⇒ Object
- #source_options ⇒ Object
-
#source_reflection ⇒ Object
Returns the source of the through reflection.
-
#source_reflection_name ⇒ Object
:nodoc:.
-
#source_reflection_names ⇒ Object
Gets an array of possible
:through
source reflection names in both singular and plural form. - #through_options ⇒ Object
-
#through_reflection ⇒ Object
Returns the AssociationReflection object specified in the
:through
option of a HasManyThrough or HasOneThrough association. - #through_reflection? ⇒ Boolean
Methods inherited from AbstractReflection
#alias_candidate, #build_association, #build_scope, #chain, #check_validity_of_inverse!, #class_name, #counter_cache_column, #counter_must_be_updated_by_has_many?, #has_cached_counter?, #inverse_of, #inverse_updates_counter_in_memory?, #inverse_which_updates_counter_cache, #join_scope, #klass_join_scope, #strict_loading?, #strict_loading_violation_message, #table_name
Constructor Details
#initialize(delegate_reflection) ⇒ ThroughReflection
Returns a new instance of ThroughReflection.
922 923 924 925 926 927 928 929 |
# File 'lib/active_record/reflection.rb', line 922 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 Method Details
#add_as_polymorphic_through(reflection, seed) ⇒ Object
1134 1135 1136 |
# File 'lib/active_record/reflection.rb', line 1134 def add_as_polymorphic_through(reflection, seed) collect_join_reflections(seed + [PolymorphicReflection.new(self, reflection)]) end |
#add_as_source(seed) ⇒ Object
1130 1131 1132 |
# File 'lib/active_record/reflection.rb', line 1130 def add_as_source(seed) collect_join_reflections seed end |
#add_as_through(seed) ⇒ Object
1138 1139 1140 |
# File 'lib/active_record/reflection.rb', line 1138 def add_as_through(seed) collect_join_reflections(seed + [self]) end |
#association_primary_key(klass = nil) ⇒ Object
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.
1027 1028 1029 1030 1031 1032 1033 1034 1035 |
# File 'lib/active_record/reflection.rb', line 1027 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! ⇒ Object
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 |
# File 'lib/active_record/reflection.rb', line 1084 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.reflections.keys.map(&:to_sym) 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 ⇒ Object
This is for clearing cache on the reflection. Useful for tests that need to compare SQL queries on associations.
999 1000 1001 1002 1003 |
# File 'lib/active_record/reflection.rb', line 999 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 ⇒ Object
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 :tags, through: :taggings
end
tags_reflection = Post.reflect_on_association(:tags)
tags_reflection.chain
# => [<ActiveRecord::Reflection::ThroughReflection: @delegate_reflection=#<ActiveRecord::Reflection::HasManyReflection: @name=:tags...>,
<ActiveRecord::Reflection::HasManyReflection: @name=:taggings, @options={}, @active_record=Post>]
993 994 995 |
# File 'lib/active_record/reflection.rb', line 993 def collect_join_chain collect_join_reflections [self] end |
#constraints ⇒ Object
1124 1125 1126 1127 1128 |
# File 'lib/active_record/reflection.rb', line 1124 def constraints scope_chain = source_reflection.constraints scope_chain << scope if scope scope_chain end |
#has_scope? ⇒ Boolean
1013 1014 1015 1016 1017 |
# File 'lib/active_record/reflection.rb', line 1013 def has_scope? scope || [:source_type] || source_reflection.has_scope? || through_reflection.has_scope? end |
#join_primary_key(klass = self.klass) ⇒ Object
1037 1038 1039 |
# File 'lib/active_record/reflection.rb', line 1037 def join_primary_key(klass = self.klass) source_reflection.join_primary_key(klass) end |
#join_scopes(table, predicate_builder, klass = self.klass, record = nil) ⇒ Object
:nodoc:
1009 1010 1011 |
# File 'lib/active_record/reflection.rb', line 1009 def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc: source_reflection.join_scopes(table, predicate_builder, klass, record) + super end |
#klass ⇒ Object
935 936 937 |
# File 'lib/active_record/reflection.rb', line 935 def klass @klass ||= delegate_reflection.compute_class(class_name) end |
#nested? ⇒ Boolean
A through association is nested if there would be more than one join table
1020 1021 1022 |
# File 'lib/active_record/reflection.rb', line 1020 def nested? source_reflection.through_reflection? || through_reflection.through_reflection? end |
#scopes ⇒ Object
1005 1006 1007 |
# File 'lib/active_record/reflection.rb', line 1005 def scopes source_reflection.scopes + super end |
#source_options ⇒ Object
1076 1077 1078 |
# File 'lib/active_record/reflection.rb', line 1076 def source_reflection. end |
#source_reflection ⇒ Object
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 :tags, through: :taggings
end
class Tagging < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
= Post.reflect_on_association(:tags)
.source_reflection
# => <ActiveRecord::Reflection::BelongsToReflection: @name=:tag, @active_record=Tagging, @plural_name="tags">
956 957 958 |
# File 'lib/active_record/reflection.rb', line 956 def source_reflection through_reflection.klass._reflect_on_association(source_reflection_name) end |
#source_reflection_name ⇒ Object
:nodoc:
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 |
# File 'lib/active_record/reflection.rb', line 1056 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 ⇒ Object
Gets an array of possible :through
source reflection names in both singular and plural form.
class Post < ActiveRecord::Base
has_many :taggings
has_many :tags, through: :taggings
end
= Post.reflect_on_association(:tags)
.source_reflection_names
# => [:tag, :tags]
1052 1053 1054 |
# File 'lib/active_record/reflection.rb', line 1052 def source_reflection_names [:source] ? [[:source]] : [name.to_s.singularize, name].uniq end |
#through_options ⇒ Object
1080 1081 1082 |
# File 'lib/active_record/reflection.rb', line 1080 def through_reflection. end |
#through_reflection ⇒ Object
Returns the AssociationReflection object specified in the :through
option of a HasManyThrough or HasOneThrough association.
class Post < ActiveRecord::Base
has_many :taggings
has_many :tags, through: :taggings
end
= Post.reflect_on_association(:tags)
.through_reflection
# => <ActiveRecord::Reflection::HasManyReflection: @name=:taggings, @active_record=Post, @plural_name="taggings">
972 973 974 |
# File 'lib/active_record/reflection.rb', line 972 def through_reflection active_record._reflect_on_association([:through]) end |
#through_reflection? ⇒ Boolean
931 932 933 |
# File 'lib/active_record/reflection.rb', line 931 def through_reflection? true end |