Skip to content

Commit 1d7f4e6

Browse files
authored
Merge pull request rails#47928 from Shopify/pm/cpk-delete
Support deleting records from associations for CPK
2 parents b20defa + 6afc035 commit 1d7f4e6

File tree

9 files changed

+73
-2
lines changed

9 files changed

+73
-2
lines changed

activerecord/lib/active_record/associations/has_many_association.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ def delete_records(records, method)
128128
records.each(&:destroy!)
129129
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
130130
else
131-
scope = self.scope.where(reflection.klass.primary_key => records)
131+
query_constraints = reflection.klass.composite_query_constraints_list
132+
values = records.map { |r| query_constraints.map { |col| r._read_attribute(col) } }
133+
scope = self.scope.where(query_constraints => values)
132134
update_counter(-delete_count(method, scope))
133135
end
134136
end

activerecord/test/cases/associations/has_many_associations_test.rb

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
require "models/zine"
4242
require "models/interest"
4343
require "models/human"
44+
require "models/sharded"
45+
require "models/cpk"
4446

4547
class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
4648
fixtures :authors, :author_addresses, :posts, :comments
@@ -116,7 +118,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
116118
fixtures :accounts, :categories, :companies, :developers, :projects,
117119
:developers_projects, :topics, :authors, :author_addresses, :comments,
118120
:posts, :readers, :taggings, :cars, :tags,
119-
:categorizations, :zines, :interests, :humans
121+
:categorizations, :zines, :interests, :humans,
122+
:sharded_blog_posts, :sharded_comments, :cpk_books, :cpk_authors
120123

121124
def setup
122125
Client.destroyed_client_ids.clear
@@ -1287,6 +1290,45 @@ def test_deleting_before_save
12871290
assert_equal 0, new_firm.clients_of_firm.size
12881291
end
12891292

1293+
def test_deleting_models_with_composite_keys
1294+
great_author = cpk_authors(:cpk_great_author)
1295+
books = great_author.books
1296+
1297+
assert_equal 2, books.size
1298+
1299+
great_author.books.delete(books.first)
1300+
great_author.reload
1301+
1302+
assert_equal 1, great_author.books.size
1303+
end
1304+
1305+
def test_sharded_deleting_models
1306+
blog_post = sharded_blog_posts(:great_post_blog_one)
1307+
comments = blog_post.delete_comments
1308+
1309+
assert_equal 3, comments.size
1310+
1311+
comments_to_delete = [comments.first, comments.second]
1312+
1313+
sql = capture_sql do
1314+
blog_post.delete_comments.delete(comments_to_delete)
1315+
end
1316+
1317+
c = Sharded::Comment.connection
1318+
1319+
blog_id = Regexp.escape(c.quote_table_name("sharded_comments.blog_id"))
1320+
id = Regexp.escape(c.quote_table_name("sharded_comments.id"))
1321+
1322+
query_constraints = /#{blog_id} = .* AND #{id} = .*/
1323+
expectation = /DELETE.*WHERE.* \(#{query_constraints} OR #{query_constraints}\)/
1324+
1325+
assert_match(expectation, sql.first)
1326+
1327+
blog_post.reload
1328+
1329+
assert_equal 1, blog_post.comments.size
1330+
end
1331+
12901332
def test_has_many_without_counter_cache_option
12911333
# Ship has a conventionally named `treasures_count` column, but the counter_cache
12921334
# option is not given on the association.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
_fixture:
2+
model_class: Cpk::Author
3+
4+
cpk_great_author:
5+
name: "Alice"
6+
7+
cpk_famous_author_first_book:
8+
name: "Bob"

activerecord/test/fixtures/cpk_books.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ _fixture:
22
model_class: Cpk::Book
33

44
cpk_great_author_first_book:
5+
author: cpk_great_author
56
title: "The first book"
67
revision: 1
78

89
cpk_great_author_second_book:
10+
author: cpk_great_author
911
title: "The second book"
1012
revision: 1
1113

1214
cpk_famous_author_first_book:
15+
author: cpk_famous_author
1316
title: "Ruby on Rails"
1417
revision: 1
1518

activerecord/test/models/cpk.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

3+
require_relative "cpk/author"
34
require_relative "cpk/book"
45
require_relative "cpk/order"
56
require_relative "cpk/order_agreement"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# frozen_string_literal: true
2+
3+
module Cpk
4+
class Author < ActiveRecord::Base
5+
self.table_name = :cpk_authors
6+
7+
has_many :books, class_name: "Cpk::Book", dependent: :delete_all
8+
end
9+
end

activerecord/test/models/cpk/book.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Book < ActiveRecord::Base
66
self.primary_key = [:author_id, :number]
77

88
belongs_to :order
9+
belongs_to :author, class_name: "Cpk::Author"
910
end
1011

1112
class BestSeller < Book

activerecord/test/models/sharded/blog_post.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class BlogPost < ActiveRecord::Base
77

88
belongs_to :blog
99
has_many :comments, query_constraints: [:blog_id, :blog_post_id]
10+
has_many :delete_comments, class_name: "Sharded::Comment", query_constraints: [:blog_id, :blog_post_id], dependent: :delete_all
1011

1112
has_many :blog_post_tags, query_constraints: [:blog_id, :blog_post_id]
1213
has_many :tags, through: :blog_post_tags

activerecord/test/schema/schema.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@
247247
t.integer :order_id
248248
end
249249

250+
create_table :cpk_authors, force: true do |t|
251+
t.string :name
252+
end
253+
250254
create_table :cpk_orders, primary_key: [:shop_id, :id], force: true do |t|
251255
t.integer :shop_id
252256
t.integer :id

0 commit comments

Comments
 (0)