Fix `destroy_all` for `has_many :through` associations that points to a CPK model

This commit is contained in:
Nikita Vasilevsky 2023-06-14 17:27:22 +00:00
parent 01363bd7e7
commit 892e4ae24c
No known key found for this signature in database
GPG Key ID: 0FF5725CD31059E4
8 changed files with 72 additions and 4 deletions

View File

@ -62,9 +62,8 @@ module ActiveRecord
if Array(association_primary_key) == reflection.klass.composite_query_constraints_list && !options[:source_type]
join_attributes = { source_reflection.name => records }
else
join_attributes = {
source_reflection.foreign_key => records.map(&association_primary_key.to_sym)
}
assoc_pk_values = records.map { |record| record._read_attribute(association_primary_key) }
join_attributes = { source_reflection.foreign_key => assoc_pk_values }
end
if options[:source_type]

View File

@ -37,13 +37,15 @@ require "models/section"
require "models/seminar"
require "models/session"
require "models/sharded"
require "models/cpk"
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
fixtures :posts, :readers, :people, :comments, :authors, :categories, :taggings, :tags,
:owners, :pets, :toys, :jobs, :references, :companies, :members, :author_addresses,
:subscribers, :books, :subscriptions, :developers, :categorizations, :essays,
:categories_posts, :clubs, :memberships, :organizations, :author_favorites,
:sharded_blog_posts, :sharded_tags, :sharded_blog_posts_tags
:sharded_blog_posts, :sharded_tags, :sharded_blog_posts_tags, :cpk_orders, :cpk_tags,
:cpk_order_tags
# Dummies to force column loads so query counts are clean.
def setup
@ -440,6 +442,16 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert_empty posts(:welcome).people.reload
end
def test_destroy_all_on_composite_primary_key_model
tag = cpk_tags(:cpk_tag_loyal_customer)
assert_not_empty(tag.orders.to_a)
tag.orders.destroy_all
assert_empty(tag.orders)
assert_empty(tag.orders.reload)
end
def test_destroy_all_on_association_clears_scope
post = Post.create!(title: "Rails 6", body: "")
people = post.people

View File

@ -0,0 +1,15 @@
_fixture:
model_class: Cpk::OrderTag
cpk_first_order_loyal_customer:
tag_id: <%= ActiveRecord::FixtureSet.identify(:cpk_tag_loyal_customer) %>
order_id: <%= ActiveRecord::FixtureSet.composite_identify(:cpk_groceries_order_1, [:shop_id, :id])[:id] %>
cpk_second_order_loyal_customer:
tag_id: <%= ActiveRecord::FixtureSet.identify(:cpk_tag_loyal_customer) %>
order_id: <%= ActiveRecord::FixtureSet.composite_identify(:cpk_groceries_order_2, [:shop_id, :id])[:id] %>
cpk_first_order_digital_product:
tag_id: <%= ActiveRecord::FixtureSet.identify(:cpk_tag_digital_product) %>
order_id: <%= ActiveRecord::FixtureSet.composite_identify(:cpk_groceries_order_1, [:shop_id, :id])[:id] %>

11
activerecord/test/fixtures/cpk_tags.yml vendored Normal file
View File

@ -0,0 +1,11 @@
_fixture:
model_class: Cpk::Tag
cpk_tag_loyal_customer:
name: "Loyal customer"
cpk_tag_digital_product:
name: "Digital product"
cpk_tag_ruby_on_rails:
name: "Ruby on Rails"

View File

@ -5,3 +5,5 @@ require_relative "cpk/book"
require_relative "cpk/order"
require_relative "cpk/review"
require_relative "cpk/order_agreement"
require_relative "cpk/order_tag"
require_relative "cpk/tag"

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Cpk
class OrderTag < ActiveRecord::Base
self.table_name = :cpk_order_tags
belongs_to :tag
belongs_to :order, primary_key: :id
end
end

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Cpk
class Tag < ActiveRecord::Base
self.table_name = :cpk_tags
has_many :order_tags
has_many :orders, through: :order_tags
end
end

View File

@ -267,6 +267,15 @@ ActiveRecord::Schema.define do
t.string :status
end
create_table :cpk_order_tags, force: true do |t|
t.integer :order_id
t.integer :tag_id
end
create_table :cpk_tags, force: true do |t|
t.string :name, null: false
end
create_table :cpk_order_agreements, force: true do |t|
t.integer :order_id
t.string :signature