Class: ActiveRecord::Reflection::ThroughReflection
- Inherits:
-
AssociationReflection
- Object
- MacroReflection
- AssociationReflection
- ActiveRecord::Reflection::ThroughReflection
- Defined in:
- activerecord/lib/active_record/reflection.rb
Overview
Holds all the meta-data about a :through association as it was specified in the Active Record class.
Instance Attribute Summary
Attributes inherited from MacroReflection
#active_record, #macro, #name, #options, #plural_name
Instance Method Summary collapse
-
#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.
-
#chain ⇒ Object
Returns an array of reflections which are involved in this association.
- #check_validity! ⇒ Object
-
#conditions ⇒ Object
Consider the following example:.
-
#nested? ⇒ Boolean
A through association is nested if there would be more than one join table.
-
#source_macro ⇒ Object
The macro used by the source association.
- #source_options ⇒ Object
-
#source_reflection ⇒ Object
Gets the source of the through reflection.
-
#source_reflection_names ⇒ Object
Gets an array of possible
:through
source reflection names:. - #through_options ⇒ Object
-
#through_reflection ⇒ Object
Returns the AssociationReflection object specified in the
:through
option of a HasManyThrough or HasOneThrough association.
Methods inherited from AssociationReflection
#active_record_primary_key, #association_class, #association_foreign_key, #belongs_to?, #build_association, #check_validity_of_inverse!, #collection?, #columns, #counter_cache_column, #foreign_key, #foreign_type, #has_inverse?, #initialize, #inverse_of, #klass, #polymorphic_inverse_of, #primary_key_column, #quoted_table_name, #reset_column_information, #table_name, #type, #validate?
Methods inherited from MacroReflection
#==, #class_name, #initialize, #klass, #sanitized_conditions
Constructor Details
This class inherits a constructor from ActiveRecord::Reflection::AssociationReflection
Instance Method Details
#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.
472 473 474 475 476 477 478 479 480 481 |
# File 'activerecord/lib/active_record/reflection.rb', line 472 def association_primary_key(klass = nil) # Get the "actual" source reflection if the immediate source reflection has a # source reflection itself source_reflection = self.source_reflection while source_reflection.source_reflection source_reflection = source_reflection.source_reflection end source_reflection.[:primary_key] || primary_key(klass || self.klass) end |
#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.
409 410 411 412 413 414 415 |
# File 'activerecord/lib/active_record/reflection.rb', line 409 def chain @chain ||= begin chain = source_reflection.chain + through_reflection.chain chain[0] = self # Use self so we don't lose the information from :source_type chain end end |
#check_validity! ⇒ Object
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'activerecord/lib/active_record/reflection.rb', line 499 def check_validity! if through_reflection.nil? raise HasManyThroughAssociationNotFoundError.new(active_record.name, self) end if through_reflection.[:polymorphic] raise HasManyThroughAssociationPolymorphicThroughError.new(active_record.name, self) end if source_reflection.nil? raise HasManyThroughSourceAssociationNotFoundError.new(self) end if [:source_type] && source_reflection.[:polymorphic].nil? 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 macro == :has_one && through_reflection.collection? raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection) end check_validity_of_inverse! end |
#conditions ⇒ Object
Consider the following example:
class Person
has_many :articles
has_many :comment_tags, :through => :articles
end
class Article
has_many :comments
has_many :comment_tags, :through => :comments, :source => :tags
end
class Comment
has_many :tags
end
There may be conditions on Person.comment_tags, Article.comment_tags and/or Comment.tags, but only Comment.tags will be represented in the #chain. So this method creates an array of conditions corresponding to the chain. Each item in the #conditions array corresponds to an item in the #chain, and is itself an array of conditions from an arbitrary number of relevant reflections, plus any :source_type or polymorphic :as constraints.
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'activerecord/lib/active_record/reflection.rb', line 438 def conditions @conditions ||= begin conditions = source_reflection.conditions.map { |c| c.dup } # Add to it the conditions from this reflection if necessary. conditions.first << [:conditions] if [:conditions] through_conditions = through_reflection.conditions if [:source_type] through_conditions.first << { foreign_type => [:source_type] } end # Recursively fill out the rest of the array from the through reflection conditions += through_conditions # And return conditions end end |
#nested? ⇒ Boolean
A through association is nested if there would be more than one join table
465 466 467 |
# File 'activerecord/lib/active_record/reflection.rb', line 465 def nested? chain.length > 2 || through_reflection.macro == :has_and_belongs_to_many end |
#source_macro ⇒ Object
The macro used by the source association
460 461 462 |
# File 'activerecord/lib/active_record/reflection.rb', line 460 def source_macro source_reflection.source_macro end |
#source_options ⇒ Object
491 492 493 |
# File 'activerecord/lib/active_record/reflection.rb', line 491 def source_reflection. end |
#source_reflection ⇒ Object
Gets 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
384 385 386 |
# File 'activerecord/lib/active_record/reflection.rb', line 384 def source_reflection @source_reflection ||= source_reflection_names.collect { |name| through_reflection.klass.reflect_on_association(name) }.compact.first end |
#source_reflection_names ⇒ Object
Gets an array of possible :through
source reflection names:
[:singularized, :pluralized]
487 488 489 |
# File 'activerecord/lib/active_record/reflection.rb', line 487 def source_reflection_names @source_reflection_names ||= ([:source] ? [[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym } end |
#through_options ⇒ Object
495 496 497 |
# File 'activerecord/lib/active_record/reflection.rb', line 495 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)
taggings_reflection = .through_reflection
399 400 401 |
# File 'activerecord/lib/active_record/reflection.rb', line 399 def through_reflection @through_reflection ||= active_record.reflect_on_association([:through]) end |