Fix belongs_to polymorphic with custom primary key on target.

Closes #3104.
This commit is contained in:
Jon Leighton
2011-09-26 15:41:31 +01:00
parent ef7de0cf24
commit 4aeb7f2eb7
5 changed files with 30 additions and 18 deletions

View File

@@ -68,7 +68,12 @@ module ActiveRecord
end
if reflection.source_macro == :belongs_to
key = reflection.association_primary_key
if reflection.options[:polymorphic]
key = reflection.association_primary_key(klass)
else
key = reflection.association_primary_key
end
foreign_key = reflection.foreign_key
else
key = reflection.foreign_key

View File

@@ -45,7 +45,11 @@ module ActiveRecord
end
def replace_keys(record)
owner[reflection.foreign_key] = record && record[reflection.association_primary_key]
if record
owner[reflection.foreign_key] = record[reflection.association_primary_key(record.class)]
else
owner[reflection.foreign_key] = nil
end
end
def foreign_key_present?

View File

@@ -223,11 +223,9 @@ module ActiveRecord
@association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
end
def association_primary_key
@association_primary_key ||=
options[:primary_key] ||
!options[:polymorphic] && klass.primary_key ||
'id'
# klass option is necessary to support loading polymorphic associations
def association_primary_key(klass = self.klass)
options[:primary_key] || klass.primary_key
end
def active_record_primary_key
@@ -475,17 +473,15 @@ module ActiveRecord
# 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.
def association_primary_key
@association_primary_key ||= begin
# 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.options[:primary_key] || klass.primary_key
def association_primary_key(klass = self.klass)
# 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.options[:primary_key] || klass.primary_key
end
# Gets an array of possible <tt>:through</tt> source reflection names:

View File

@@ -13,6 +13,7 @@ require 'models/comment'
require 'models/sponsor'
require 'models/member'
require 'models/essay'
require 'models/toy'
class BelongsToAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :topics,
@@ -687,4 +688,11 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal nil, comment.reload.parent
assert_equal 0, comments(:greetings).reload.children_count
end
def test_polymorphic_with_custom_primary_key
toy = Toy.create!
sponsor = Sponsor.create!(:sponsorable => toy)
assert_equal toy, sponsor.reload.sponsorable
end
end

View File

@@ -244,7 +244,6 @@ class ReflectionTest < ActiveRecord::TestCase
# Normal association
assert_equal "id", Author.reflect_on_association(:posts).association_primary_key.to_s
assert_equal "name", Author.reflect_on_association(:essay).association_primary_key.to_s
assert_equal "id", Tagging.reflect_on_association(:taggable).association_primary_key.to_s
# Through association (uses the :primary_key option from the source reflection)
assert_equal "nick", Author.reflect_on_association(:subscribers).association_primary_key.to_s