mirror of https://github.com/rails/rails
Fix associations associated with a CPK model by id attribute
Given a model associated with a composite primary key by `id` attribute, for example: ```ruby Order.primary_key = [:shop_id, :id] OrderAgreement.primary_key = :id Order.has_many :order_agreements, primary_key: :id ``` Accessing the association should perform queries using the `id` attribute value and not the `id` as Order's composite primary key. ```ruby order = Order.last # => #<Order id: 1, shop_id: 2> order.order_agreements.to_a ```
This commit is contained in:
parent
e11ebc04cf
commit
5cbdfba670
|
@ -62,7 +62,7 @@ module ActiveRecord
|
|||
table = reflection.aliased_table
|
||||
primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
|
||||
primary_key_foreign_key_pairs.each do |join_key, foreign_key|
|
||||
value = transform_value(owner[foreign_key])
|
||||
value = transform_value(owner._read_attribute(foreign_key))
|
||||
scope = apply_scope(scope, table, join_key, value)
|
||||
end
|
||||
|
||||
|
|
|
@ -550,7 +550,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def join_id_for(owner) # :nodoc:
|
||||
Array(join_foreign_key).map { |key| owner[key] }
|
||||
Array(join_foreign_key).map { |key| owner._read_attribute(key) }
|
||||
end
|
||||
|
||||
def through_reflection
|
||||
|
|
|
@ -35,6 +35,7 @@ require "models/essay"
|
|||
require "models/member"
|
||||
require "models/membership"
|
||||
require "models/sharded"
|
||||
require "models/cpk"
|
||||
require "models/member_detail"
|
||||
require "models/organization"
|
||||
|
||||
|
@ -42,7 +43,8 @@ require "models/organization"
|
|||
class AssociationsTest < ActiveRecord::TestCase
|
||||
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
|
||||
:computers, :people, :readers, :authors, :author_addresses, :author_favorites,
|
||||
:comments, :posts, :sharded_blogs, :sharded_blog_posts, :sharded_comments, :sharded_tags, :sharded_blog_posts_tags
|
||||
:comments, :posts, :sharded_blogs, :sharded_blog_posts, :sharded_comments, :sharded_tags, :sharded_blog_posts_tags,
|
||||
:cpk_orders
|
||||
|
||||
def test_eager_loading_should_not_change_count_of_children
|
||||
liquid = Liquid.create(name: "salty")
|
||||
|
@ -136,6 +138,14 @@ class AssociationsTest < ActiveRecord::TestCase
|
|||
assert_equal(blog_post, comment.blog_post)
|
||||
end
|
||||
|
||||
def test_belongs_to_a_cpk_model_by_id_attribute
|
||||
order = cpk_orders(:cpk_groceries_order_1)
|
||||
_order_shop_id, order_id = order.id
|
||||
agreement = Cpk::OrderAgreement.create(order_id: order_id, signature: "signed")
|
||||
|
||||
assert_equal(order, agreement.order)
|
||||
end
|
||||
|
||||
def test_belongs_to_a_model_with_composite_primary_key_uses_composite_pk_in_sql
|
||||
comment = sharded_comments(:great_comment_blog_post_one)
|
||||
|
||||
|
@ -164,6 +174,14 @@ class AssociationsTest < ActiveRecord::TestCase
|
|||
assert_includes(comments, sharded_comments(:great_comment_blog_post_one))
|
||||
end
|
||||
|
||||
def test_cpk_model_has_many_records_by_id_attribute
|
||||
order = cpk_orders(:cpk_groceries_order_1)
|
||||
_order_shop_id, order_id = order.id
|
||||
agreements = 2.times.map { Cpk::OrderAgreement.create(order_id: order_id, signature: "signed") }
|
||||
|
||||
assert_equal(agreements.sort, order.order_agreements.to_a.sort)
|
||||
end
|
||||
|
||||
def test_has_many_association_from_a_model_with_query_constraints_different_from_the_association
|
||||
blog_post = sharded_blog_posts(:great_post_blog_one)
|
||||
blog_post = Sharded::BlogPostWithRevision.find(blog_post.id)
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
require_relative "cpk/book"
|
||||
require_relative "cpk/order"
|
||||
require_relative "cpk/order_agreement"
|
||||
|
|
|
@ -4,5 +4,7 @@ module Cpk
|
|||
class Order < ActiveRecord::Base
|
||||
self.table_name = :cpk_orders
|
||||
self.primary_key = [:shop_id, :id]
|
||||
|
||||
has_many :order_agreements, primary_key: :id
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Cpk
|
||||
# This is a non composite primary key model that is associated with `Cpk::Order` via `id` only.
|
||||
class OrderAgreement < ActiveRecord::Base
|
||||
self.table_name = :cpk_order_agreements
|
||||
|
||||
belongs_to :order, primary_key: :id # foreign key is derived as `order_id`
|
||||
end
|
||||
end
|
|
@ -252,6 +252,13 @@ ActiveRecord::Schema.define do
|
|||
t.string :status
|
||||
end
|
||||
|
||||
create_table :cpk_order_agreements, force: true do |t|
|
||||
t.integer :order_id
|
||||
t.string :signature
|
||||
|
||||
t.index :order_id
|
||||
end
|
||||
|
||||
create_table :paragraphs, force: true do |t|
|
||||
t.references :book
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue