Fix eager loading of composite primary key associations

Co-Authored-By: Christine Belan <christine.belan@shopify.com>
This commit is contained in:
Nikita Vasilevsky 2024-01-22 21:18:19 +00:00
parent fe81d667a7
commit 605d910194
No known key found for this signature in database
GPG Key ID: 0FF5725CD31059E4
4 changed files with 27 additions and 7 deletions

View File

@ -254,10 +254,10 @@ module ActiveRecord
if node.primary_key
keys = Array(node.primary_key).map { |column| aliases.column_alias(node, column) }
ids = keys.map { |key| row[key] }
id = keys.map { |key| row[key] }
else
keys = Array(node.reflection.join_primary_key).map { |column| aliases.column_alias(node, column.to_s) }
ids = keys.map { nil } # Avoid id-based model caching.
id = keys.map { nil } # Avoid id-based model caching.
end
if keys.any? { |key| row[key].nil? }
@ -266,11 +266,9 @@ module ActiveRecord
next
end
ids.each do |id|
unless model = seen[ar_parent][node][id]
model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
seen[ar_parent][node][id] = model if id
end
unless model = seen[ar_parent][node][id]
model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
seen[ar_parent][node][id] = model if id
end
construct(model, node, row, seen, model_cache, strict_loading_value)

View File

@ -1729,6 +1729,26 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal(expected_tag_ids.sort, blog_post.tags.map(&:id).sort)
end
test "preloading belongs_to CPK model with one of the keys being shared between models" do
post1 = Cpk::Post.create!(title: "post1", author: "the_same_author")
Cpk::Comment.create!(post: post1, text: "great post1!")
post2 = Cpk::Post.create!(title: "post2", author: "the_same_author")
Cpk::Comment.create!(post: post2, text: "great post2!")
comments = Cpk::Comment.eager_load(:post).to_a
expected = {
"great post1!" => "post1",
"great post2!" => "post2"
}
actual = comments.each_with_object({}) do |comment, hash|
hash[comment.text] = comment.post.title
end
assert_equal expected, actual
end
test "preloading belongs_to with cpk" do
order = Cpk::Order.create!(shop_id: 2)
order_agreement = Cpk::OrderAgreement.create!(order: order)

View File

@ -4,5 +4,6 @@ module Cpk
class Comment < ActiveRecord::Base
self.table_name = :cpk_comments
belongs_to :commentable, class_name: "Cpk::Post", query_constraints: %i[commentable_title commentable_author], polymorphic: true
belongs_to :post, class_name: "Cpk::Post", query_constraints: %i[commentable_title commentable_author]
end
end

View File

@ -270,6 +270,7 @@ ActiveRecord::Schema.define do
t.string :commentable_title
t.string :commentable_author
t.string :commentable_type
t.text :text
end
create_table :cpk_reviews, force: true do |t|