Skip to content
Browse files

Fix problem with loading polymorphic associations which have been def…

…ined in an abstract superclass. Fixes #552.
  • Loading branch information...
1 parent 3cbfc8c commit 872a9c1b50a4f881d9c18d759a86d1b33714c384 @jonleighton jonleighton committed
View
20 activerecord/lib/active_record/associations/association_scope.rb
@@ -75,10 +75,16 @@ def add_constraints(scope)
foreign_key = reflection.active_record_primary_key
end
+ conditions = self.conditions[i]
+
if reflection == chain.last
scope = scope.where(table[key].eq(owner[foreign_key]))
- conditions[i].each do |condition|
+ if reflection.type
+ scope = scope.where(table[reflection.type].eq(owner.class.base_class.name))
+ end
+
+ conditions.each do |condition|
if options[:through] && condition.is_a?(Hash)
condition = { table.name => condition }
end
@@ -87,12 +93,16 @@ def add_constraints(scope)
end
else
constraint = table[key].eq(foreign_table[foreign_key])
- join = join(foreign_table, constraint)
- scope = scope.joins(join)
+ if reflection.type
+ type = chain[i + 1].klass.base_class.name
+ constraint = constraint.and(table[reflection.type].eq(type))
+ end
+
+ scope = scope.joins(join(foreign_table, constraint))
- unless conditions[i].empty?
- scope = scope.where(sanitize(conditions[i], table))
+ unless conditions.empty?
+ scope = scope.where(sanitize(conditions, table))
end
end
end
View
10 activerecord/lib/active_record/associations/join_dependency/join_association.rb
@@ -62,6 +62,7 @@ def find_parent_in(other_join_dependency)
def join_to(relation)
tables = @tables.dup
foreign_table = parent_table
+ foreign_klass = parent.active_record
# The chain starts with the target table, but we want to end with it here (makes
# more sense in this context), so we reverse
@@ -91,14 +92,17 @@ def join_to(relation)
constraint = build_constraint(reflection, table, key, foreign_table, foreign_key)
- unless conditions[i].empty?
- constraint = constraint.and(sanitize(conditions[i], table))
+ conditions = self.conditions[i].dup
+ conditions << { reflection.type => foreign_klass.base_class.name } if reflection.type
+
+ unless conditions.empty?
+ constraint = constraint.and(sanitize(conditions, table))
end
relation.from(join(table, constraint))
# The current table in this iteration becomes the foreign table in the next
- foreign_table = table
+ foreign_table, foreign_klass = table, reflection.klass
end
relation
View
9 activerecord/lib/active_record/reflection.rb
@@ -212,7 +212,7 @@ def foreign_type
end
def type
- @type ||= "#{options[:as]}_type"
+ @type ||= options[:as] && "#{options[:as]}_type"
end
def primary_key_column
@@ -280,9 +280,7 @@ def chain
# in the #chain. The inside arrays are simply conditions (and each condition may itself be
# a hash, array, arel predicate, etc...)
def conditions
- conditions = [options[:conditions]].compact
- conditions << { type => active_record.base_class.name } if options[:as]
- [conditions]
+ [[options[:conditions]].compact]
end
alias :source_macro :macro
@@ -378,7 +376,8 @@ def derive_foreign_key
# Holds all the meta-data about a :through association as it was specified
# in the Active Record class.
class ThroughReflection < AssociationReflection #:nodoc:
- delegate :foreign_key, :foreign_type, :association_foreign_key, :active_record_primary_key, :to => :source_reflection
+ delegate :foreign_key, :foreign_type, :association_foreign_key,
+ :active_record_primary_key, :type, :to => :source_reflection
# Gets the source of the through reflection. It checks both a singularized
# and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>.
View
7 activerecord/test/cases/associations/has_many_associations_test.rb
@@ -11,6 +11,7 @@
require 'models/person'
require 'models/reader'
require 'models/tagging'
+require 'models/tag'
require 'models/invoice'
require 'models/line_item'
require 'models/car'
@@ -1468,4 +1469,10 @@ def test_new_is_called_with_attributes_and_options
bulb = car.bulbs.build({ :bulb_type => :custom }, :as => :admin)
assert_equal CustomBulb, bulb.class
end
+
+ def test_abstract_class_with_polymorphic_has_many
+ post = SubStiPost.create! :title => "fooo", :body => "baa"
+ tagging = Tagging.create! :taggable => post
+ assert_equal [tagging], post.taggings
+ end
end
View
4 activerecord/test/cases/reflection_test.rb
@@ -216,7 +216,7 @@ def test_chain
def test_conditions
expected = [
[{ :tags => { :name => 'Blue' } }],
- [{ :taggings => { :comment => 'first' } }, { "taggable_type" => "Post" }],
+ [{ :taggings => { :comment => 'first' } }],
[{ :posts => { :title => ['misc post by bob', 'misc post by mary'] } }]
]
actual = Author.reflect_on_association(:misc_post_first_blue_tags).conditions
@@ -224,7 +224,7 @@ def test_conditions
expected = [
[{ :tags => { :name => 'Blue' } }, { :taggings => { :comment => 'first' } }, { :posts => { :title => ['misc post by bob', 'misc post by mary'] } }],
- [{ "taggable_type" => "Post" }],
+ [],
[]
]
actual = Author.reflect_on_association(:misc_post_first_blue_tags_2).conditions

0 comments on commit 872a9c1

Please sign in to comment.
Something went wrong with that request. Please try again.