Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix various issues with the :primary_key option in :through associati…

…ons [#2421 state:resolved]
  • Loading branch information...
commit 14b880fd035fcdf807051398674c9aa89bd3b4d3 1 parent 09ddca6
@jonleighton jonleighton authored tenderlove committed
View
26 activerecord/lib/active_record/associations/through_association_scope.rb
@@ -39,22 +39,22 @@ def aliased_through_table
# Build SQL conditions from attributes, qualified by table name.
def construct_conditions
table = aliased_through_table
- conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value|
+ conditions = construct_owner_attributes(@reflection.through_reflection).map do |attr, value|
table[attr].eq(value)
end
conditions << Arel.sql(sql_conditions) if sql_conditions
table.create_and(conditions)
end
- # Associate attributes pointing to owner, quoted.
- def construct_quoted_owner_attributes(reflection)
+ # Associate attributes pointing to owner
+ def construct_owner_attributes(reflection)
if as = reflection.options[:as]
- { "#{as}_id" => @owner.id,
+ { "#{as}_id" => @owner[reflection.active_record_primary_key],
"#{as}_type" => @owner.class.base_class.name }
elsif reflection.macro == :belongs_to
{ reflection.klass.primary_key => @owner[reflection.primary_key_name] }
else
- { reflection.primary_key_name => @owner.id }
+ { reflection.primary_key_name => @owner[reflection.active_record_primary_key] }
end
end
@@ -74,7 +74,8 @@ def construct_joins
conditions = []
if @reflection.source_reflection.macro == :belongs_to
- reflection_primary_key = @reflection.klass.primary_key
+ reflection_primary_key = @reflection.source_reflection.options[:primary_key] ||
+ @reflection.klass.primary_key
source_primary_key = @reflection.source_reflection.primary_key_name
if @reflection.options[:source_type]
column = @reflection.source_reflection.options[:foreign_type]
@@ -83,7 +84,8 @@ def construct_joins
end
else
reflection_primary_key = @reflection.source_reflection.primary_key_name
- source_primary_key = @reflection.through_reflection.klass.primary_key
+ source_primary_key = @reflection.source_reflection.options[:primary_key] ||
+ @reflection.through_reflection.klass.primary_key
if @reflection.source_reflection.options[:as]
column = "#{@reflection.source_reflection.options[:as]}_type"
conditions <<
@@ -99,16 +101,6 @@ def construct_joins
right.create_on(right.create_and(conditions)))
end
- # Construct attributes for associate pointing to owner.
- def construct_owner_attributes(reflection)
- if as = reflection.options[:as]
- { "#{as}_id" => @owner.id,
- "#{as}_type" => @owner.class.base_class.name }
- else
- { reflection.primary_key_name => @owner.id }
- end
- end
-
# Construct attributes for :through pointing to owner and associate.
def construct_join_attributes(associate)
# TODO: revisit this to allow it for deletion, supposing dependent option is supported
View
6 activerecord/lib/active_record/reflection.rb
@@ -205,7 +205,11 @@ def primary_key_column
end
def association_foreign_key
- @association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key
+ @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
+ end
+
+ def active_record_primary_key
+ @active_record_primary_key ||= options[:primary_key] || active_record.primary_key
end
def counter_cache_column
View
16 activerecord/test/cases/associations/join_model_test.rb
@@ -298,6 +298,22 @@ def test_has_many_going_through_join_model_with_custom_foreign_key
assert_equal [authors(:mary)], posts(:authorless).authors
end
+ def test_has_many_going_through_join_model_with_custom_primary_key
+ assert_equal [authors(:david)], posts(:thinking).authors_using_author_id
+ end
+
+ def test_has_many_going_through_polymorphic_join_model_with_custom_primary_key
+ assert_equal [tags(:general)], posts(:eager_other).tags_using_author_id
+ end
+
+ def test_has_many_through_with_custom_primary_key_on_belongs_to_source
+ assert_equal [authors(:david), authors(:david)], posts(:thinking).author_using_custom_pk
+ end
+
+ def test_has_many_through_with_custom_primary_key_on_has_many_source
+ assert_equal [authors(:david)], posts(:thinking).authors_using_custom_pk
+ end
+
def test_both_scoped_and_explicit_joins_should_be_respected
assert_nothing_raised do
Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
View
5 activerecord/test/cases/reflection_test.rb
@@ -191,6 +191,11 @@ def test_has_many_through_reflection
assert_kind_of ThroughReflection, Subscriber.reflect_on_association(:books)
end
+ def test_active_record_primary_key
+ assert_equal "nick", Subscriber.reflect_on_association(:subscriptions).active_record_primary_key.to_s
+ assert_equal "name", Author.reflect_on_association(:essay).active_record_primary_key.to_s
+ end
+
def test_collection_association
assert Pirate.reflect_on_association(:birds).collection?
assert Pirate.reflect_on_association(:parrots).collection?
View
3  activerecord/test/models/categorization.rb
@@ -2,6 +2,9 @@ class Categorization < ActiveRecord::Base
belongs_to :post
belongs_to :category
belongs_to :author
+
+ belongs_to :author_using_custom_pk, :class_name => 'Author', :foreign_key => :author_id, :primary_key => :author_address_extra_id
+ has_many :authors_using_custom_pk, :class_name => 'Author', :foreign_key => :id, :primary_key => :category_id
end
class SpecialCategorization < ActiveRecord::Base
View
10 activerecord/test/models/post.rb
@@ -69,6 +69,16 @@ def add_joins_and_select
has_many :categorizations, :foreign_key => :category_id
has_many :authors, :through => :categorizations
+ has_many :categorizations_using_author_id, :primary_key => :author_id, :foreign_key => :post_id, :class_name => 'Categorization'
+ has_many :authors_using_author_id, :through => :categorizations_using_author_id, :source => :author
+
+ has_many :taggings_using_author_id, :primary_key => :author_id, :as => :taggable, :class_name => 'Tagging'
+ has_many :tags_using_author_id, :through => :taggings_using_author_id, :source => :tag
+
+ has_many :standard_categorizations, :class_name => 'Categorization', :foreign_key => :post_id
+ has_many :author_using_custom_pk, :through => :standard_categorizations
+ has_many :authors_using_custom_pk, :through => :standard_categorizations
+
has_many :readers
has_many :readers_with_person, :include => :person, :class_name => "Reader"
has_many :people, :through => :readers
Please sign in to comment.
Something went wrong with that request. Please try again.