Skip to content

Commit fb5cef9

Browse files
committed
Configure query_constraints_list to use primary_key by default
Every `ActiveRecord::Base` model now should have `query_constraints_list` configured by default and its value set to the model's `primary_key`
1 parent 38d7915 commit fb5cef9

File tree

8 files changed

+79
-24
lines changed

8 files changed

+79
-24
lines changed

activerecord/lib/active_record/persistence.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,8 +1048,6 @@ def _find_record(options)
10481048
end
10491049

10501050
def _in_memory_query_constraints_hash
1051-
return { @primary_key => id } unless self.class.query_constraints_list
1052-
10531051
self.class.query_constraints_list.index_with do |column_name|
10541052
attribute(column_name)
10551053
end
@@ -1061,8 +1059,6 @@ def apply_scoping?(options)
10611059
end
10621060

10631061
def _query_constraints_hash
1064-
return { @primary_key => id_in_database } unless self.class.query_constraints_list
1065-
10661062
self.class.query_constraints_list.index_with do |column_name|
10671063
attribute_in_database(column_name)
10681064
end

activerecord/lib/active_record/query_constraints.rb

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ module ActiveRecord
44
module QueryConstraints
55
extend ActiveSupport::Concern
66

7-
included do
8-
class_attribute :query_constraints_list, instance_writer: false
9-
end
10-
117
module ClassMethods
128
# Accepts a list of attribute names to be used in the WHERE clause
139
# of SELECT / UPDATE / DELETE queries.
@@ -39,8 +35,24 @@ module ClassMethods
3935
# developer.reload
4036
# # => SELECT "developers".* FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1 LIMIT 1
4137
def query_constraints(*columns_list)
42-
self.query_constraints_list = columns_list.map(&:to_s)
38+
@_query_constraints_list = columns_list.map(&:to_s)
39+
end
40+
41+
def query_constraints_list # :nodoc:
42+
@_query_constraints_list ||= query_constraints_list_fallback
4343
end
44+
45+
private
46+
# This is a fallback method that is used to determine the query_constraints_list
47+
# for cases when the model is not explicitly configured with query_constraints.
48+
# For a base class, just use the primary key.
49+
# For a child class, use the primary key unless primary key was overridden.
50+
# If the child's primary key was not overridden, use the parent's query_constraints_list.
51+
def query_constraints_list_fallback # :nodoc:
52+
return Array(primary_key) if base_class? || primary_key != base_class.primary_key
53+
54+
base_class.query_constraints_list
55+
end
4456
end
4557
end
4658
end

activerecord/test/cases/persistence_test.rb

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
require "cases/helper"
44
require "models/aircraft"
5+
require "models/dashboard"
6+
require "models/clothing_item"
57
require "models/post"
68
require "models/comment"
79
require "models/author"
@@ -19,7 +21,6 @@
1921
require "models/ship"
2022
require "models/admin"
2123
require "models/admin/user"
22-
require "models/clothing_item"
2324

2425
class PersistenceTest < ActiveRecord::TestCase
2526
fixtures :topics, :companies, :developers, :accounts, :minimalistics, :authors, :author_addresses,
@@ -1396,3 +1397,49 @@ def test_it_is_possible_to_update_parts_of_the_query_constraints_config
13961397
assert_equal("blue", ClothingItem.find_by(id: clothing_item.id).color)
13971398
end
13981399
end
1400+
1401+
class QueryConstraintsTest < ActiveRecord::TestCase
1402+
fixtures :clothing_items, :dashboards, :topics, :posts
1403+
1404+
def test_primary_key_stays_the_same
1405+
assert_equal("id", ClothingItem.primary_key)
1406+
end
1407+
1408+
def test_query_constraints_uses_primary_key_by_default
1409+
post = posts(:welcome)
1410+
assert_uses_query_constraints_on_reload(post, "id")
1411+
end
1412+
1413+
def test_query_constraints_uses_manually_configured_primary_key
1414+
dashboard = dashboards(:cool_first)
1415+
assert_uses_query_constraints_on_reload(dashboard, "dashboard_id")
1416+
end
1417+
1418+
def test_child_overriden_primary_key_is_used_as_query_constraint
1419+
topic = topics(:first)
1420+
assert_uses_query_constraints_on_reload(topic, "id")
1421+
1422+
title_pk_topic = topic.becomes(TitlePrimaryKeyTopic)
1423+
title_pk_topic.author_name = "Nikita"
1424+
1425+
sql = capture_sql { title_pk_topic.save }.first
1426+
assert_match(/WHERE .*title/, sql)
1427+
end
1428+
1429+
def test_child_keeps_parents_query_constraints
1430+
clothing_item = clothing_items(:green_t_shirt)
1431+
assert_uses_query_constraints_on_reload(clothing_item, ["clothing_type", "color"])
1432+
1433+
used_clothing_item = clothing_items(:used_blue_jeans)
1434+
assert_uses_query_constraints_on_reload(used_clothing_item, ["clothing_type", "color"])
1435+
end
1436+
1437+
def assert_uses_query_constraints_on_reload(object, columns)
1438+
flunk("columns argument must not be empty") if columns.blank?
1439+
1440+
sql = capture_sql { object.reload }.first
1441+
Array(columns).each do |column|
1442+
assert_match(/WHERE .*#{column}/, sql)
1443+
end
1444+
end
1445+
end

activerecord/test/cases/query_constraints_test.rb

Lines changed: 0 additions & 14 deletions
This file was deleted.

activerecord/test/fixtures/clothing_items.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,22 @@ green_pants:
22
color: green
33
clothing_type: pants
44
description: Cool green pants
5+
type: ClothingItem
56

67
green_t_shirt:
78
color: green
89
clothing_type: t-shirt
910
description: Cool green t-shirt
11+
type: ClothingItem
1012

1113
red_t_shirt:
1214
color: red
1315
clothing_type: t-shirt
1416
description: Cool red t-shirt
17+
type: ClothingItem
18+
19+
used_blue_jeans:
20+
color: blue
21+
clothing_type: pants
22+
description: Cool blue jeans
23+
type: ClothingItem::Used

activerecord/test/fixtures/topics.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ fifth:
4747
written_on: 2013-07-13t12:11:00.0099+01:00
4848
content: "--- Omakase\n...\n"
4949
approved: true
50+

activerecord/test/models/clothing_item.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
class ClothingItem < ActiveRecord::Base
44
query_constraints :clothing_type, :color
55
end
6+
7+
class ClothingItem::Used < ClothingItem
8+
end

activerecord/test/schema/schema.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@
236236
create_table :clothing_items, force: true do |t|
237237
t.string :clothing_type
238238
t.string :color
239+
t.string :type
239240
t.text :description
240241

241242
t.index [:clothing_type, :color], unique: true

0 commit comments

Comments
 (0)