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
- #deprecated_nested_reflections ⇒ 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 = nil, 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
:throughsource reflection names in both singular and plural form. - #through_options ⇒ Object
-
#through_reflection ⇒ Object
Returns the AssociationReflection object specified in the
:throughoption 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_active_cached_counter?, #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.
988 989 990 991 992 993 994 995 996 997 |
# File 'lib/active_record/reflection.rb', line 988 def initialize(delegate_reflection) super() @validated = false @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
1208 1209 1210 |
# File 'lib/active_record/reflection.rb', line 1208 def add_as_polymorphic_through(reflection, seed) collect_join_reflections(seed + [PolymorphicReflection.new(self, reflection)]) end |
#add_as_source(seed) ⇒ Object
1204 1205 1206 |
# File 'lib/active_record/reflection.rb', line 1204 def add_as_source(seed) collect_join_reflections seed end |
#add_as_through(seed) ⇒ Object
1212 1213 1214 |
# File 'lib/active_record/reflection.rb', line 1212 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.
1097 1098 1099 1100 1101 1102 1103 1104 1105 |
# File 'lib/active_record/reflection.rb', line 1097 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
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 |
# File 'lib/active_record/reflection.rb', line 1154 def check_validity! return if @validated 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! @validated = true 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.
1069 1070 1071 1072 1073 |
# File 'lib/active_record/reflection.rb', line 1069 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
= Post.reflect_on_association(:tags)
.chain
# => [<ActiveRecord::Reflection::ThroughReflection: @delegate_reflection=#<ActiveRecord::Reflection::HasManyReflection: @name=:tags...>,
<ActiveRecord::Reflection::HasManyReflection: @name=:taggings, ={}, @active_record=Post>]
1063 1064 1065 |
# File 'lib/active_record/reflection.rb', line 1063 def collect_join_chain collect_join_reflections [self] end |
#constraints ⇒ Object
1198 1199 1200 1201 1202 |
# File 'lib/active_record/reflection.rb', line 1198 def constraints scope_chain = source_reflection.constraints scope_chain << scope if scope scope_chain end |
#deprecated_nested_reflections ⇒ Object
1216 1217 1218 |
# File 'lib/active_record/reflection.rb', line 1216 def deprecated_nested_reflections @deprecated_nested_reflections ||= collect_deprecated_nested_reflections end |
#has_scope? ⇒ Boolean
1083 1084 1085 1086 1087 |
# File 'lib/active_record/reflection.rb', line 1083 def has_scope? scope || [:source_type] || source_reflection.has_scope? || through_reflection.has_scope? end |
#join_primary_key(klass = self.klass) ⇒ Object
1107 1108 1109 |
# File 'lib/active_record/reflection.rb', line 1107 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) ⇒ Object
:nodoc:
1079 1080 1081 |
# File 'lib/active_record/reflection.rb', line 1079 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 ⇒ Object
1003 1004 1005 |
# File 'lib/active_record/reflection.rb', line 1003 def klass @klass ||= delegate_reflection._klass(class_name) end |
#nested? ⇒ Boolean
A through association is nested if there would be more than one join table
1090 1091 1092 |
# File 'lib/active_record/reflection.rb', line 1090 def nested? source_reflection.through_reflection? || through_reflection.through_reflection? end |
#scopes ⇒ Object
1075 1076 1077 |
# File 'lib/active_record/reflection.rb', line 1075 def scopes source_reflection.scopes + super end |
#source_options ⇒ Object
1146 1147 1148 |
# File 'lib/active_record/reflection.rb', line 1146 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">
1024 1025 1026 1027 1028 |
# File 'lib/active_record/reflection.rb', line 1024 def source_reflection return unless source_reflection_name through_reflection.klass._reflect_on_association(source_reflection_name) end |
#source_reflection_name ⇒ Object
:nodoc:
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 |
# File 'lib/active_record/reflection.rb', line 1126 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]
1122 1123 1124 |
# File 'lib/active_record/reflection.rb', line 1122 def source_reflection_names [:source] ? [[:source]] : [name.to_s.singularize, name].uniq end |
#through_options ⇒ Object
1150 1151 1152 |
# File 'lib/active_record/reflection.rb', line 1150 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">
1042 1043 1044 |
# File 'lib/active_record/reflection.rb', line 1042 def through_reflection active_record._reflect_on_association([:through]) end |
#through_reflection? ⇒ Boolean
999 1000 1001 |
# File 'lib/active_record/reflection.rb', line 999 def through_reflection? true end |