Skip to content

Commit eb06dce

Browse files
authored
Merge pull request rails#45943 from quadule/reset-relation-after-bulk-updates
Reset AR::Relation in bulk insert and upsert methods
2 parents 2cbad3f + a059197 commit eb06dce

File tree

6 files changed

+51
-5
lines changed

6 files changed

+51
-5
lines changed

activerecord/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
* Reset relations after `insert_all`/`upsert_all`.
2+
3+
Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
4+
5+
*Milo Winningham*
6+
17
* Use `_N` as a parallel tests databases suffixes
28

39
Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes

activerecord/lib/active_record/association_relation.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def ==(other)
1717

1818
%w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
1919
class_eval <<~RUBY, __FILE__, __LINE__ + 1
20-
def #{method}(attributes, **kwargs)
20+
def #{method}(...)
2121
if @association.reflection.through_reflection?
2222
raise ArgumentError, "Bulk insert or upsert is currently not supported for has_many through association"
2323
end

activerecord/lib/active_record/associations/collection_proxy.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,14 +1125,20 @@ def pretty_print(pp) # :nodoc:
11251125
super
11261126
end
11271127

1128+
%w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
1129+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
1130+
def #{method}(...)
1131+
scope.#{method}(...).tap { reset }
1132+
end
1133+
RUBY
1134+
end
1135+
11281136
delegate_methods = [
11291137
QueryMethods,
11301138
SpawnMethods,
11311139
].flat_map { |klass|
11321140
klass.public_instance_methods(false)
1133-
} - self.public_instance_methods(false) - [:select] + [
1134-
:scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all, :load_async
1135-
]
1141+
} - self.public_instance_methods(false) - [ :select ] + [ :scoping, :values, :load_async ]
11361142

11371143
delegate(*delegate_methods, to: :scope)
11381144

activerecord/lib/active_record/insert_all.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class << self
1111
def execute(relation, ...)
1212
relation.model.with_connection do |c|
1313
new(relation, c, ...).execute
14-
end
14+
end.tap { relation.reset }
1515
end
1616
end
1717

activerecord/test/cases/collection_cache_key_test.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,24 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase
9696
assert_match(/\Acomments\/query-(\h+)-(\d+)-(\d+)\z/, comments.cache_key)
9797
end
9898

99+
test "insert_all will update cache_key" do
100+
developers = Developer.all
101+
cache_key = developers.cache_key
102+
103+
developers.insert_all([{ name: "Alice" }, { name: "Bob" }])
104+
105+
assert_not_equal cache_key, developers.cache_key
106+
end
107+
108+
test "upsert_all will update cache_key" do
109+
developers = Developer.all
110+
cache_key = developers.cache_key
111+
112+
developers.upsert_all([{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }])
113+
114+
assert_not_equal cache_key, developers.cache_key
115+
end
116+
99117
test "update_all will update cache_key" do
100118
developers = Developer.where(name: "David")
101119
cache_key = developers.cache_key

activerecord/test/cases/insert_all_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,14 @@ def test_insert_all_on_relation_precedence
729729
end
730730
end
731731

732+
def test_insert_all_resets_relation
733+
audit_logs = Developer.create!(name: "Alice").audit_logs.load
734+
735+
assert_changes "audit_logs.loaded?", from: true, to: false do
736+
audit_logs.insert_all!([{ message: "event" }])
737+
end
738+
end
739+
732740
def test_insert_all_create_with
733741
assert_difference "Book.where(format: 'X').count", +2 do
734742
Book.create_with(format: "X").insert_all!([ { name: "A" }, { name: "B" } ])
@@ -761,6 +769,14 @@ def test_upsert_all_on_relation_precedence
761769
end
762770
end
763771

772+
def test_upsert_all_resets_relation
773+
audit_logs = Developer.create!(name: "Alice").audit_logs.load
774+
775+
assert_changes "audit_logs.loaded?", from: true, to: false do
776+
audit_logs.upsert_all([{ id: 1, message: "event" }])
777+
end
778+
end
779+
764780
def test_upsert_all_create_with
765781
skip unless supports_insert_on_duplicate_update?
766782

0 commit comments

Comments
 (0)