1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Avoid scoping update transaction when calling update! on a relation

This makes scoping consistent with ActiveRecord::Relation#update.
ActiveRecord::Relation#update was defined specifically to avoid this
unexpected scoping in Active Record callbacks triggered from the update
which otherwise get introduced by ActiveRecord::Relation#method_missing.
This commit is contained in:
Dylan Thacker-Smith 2021-09-09 11:41:14 -04:00
parent a8c4c27a81
commit de7ca90538
3 changed files with 33 additions and 0 deletions

View file

@ -1,3 +1,10 @@
* Avoid scoping update callbacks in `ActiveRecord::Relation#update!`.
Making it consistent with how scoping is applied only to the query in `ActiveRecord::Relation#update`
and not also to the callbacks from the update itself.
*Dylan Thacker-Smith*
* Fix 2 cases that inferred polymorphic class from the association's `foreign_type`
using `String#constantize` instead of the model's `polymorphic_class_for`.

View file

@ -498,6 +498,14 @@ module ActiveRecord
end
end
def update!(id = :all, attributes) # :nodoc:
if id == :all
each { |record| record.update!(attributes) }
else
klass.update!(id, attributes)
end
end
# Updates the counters of the records in the current relation.
#
# ==== Parameters

View file

@ -173,6 +173,24 @@ class UpdateAllTest < ActiveRecord::TestCase
end
end
def test_update_bang_on_relation
topic1 = TopicWithCallbacks.create! title: "arel", author_name: nil
topic2 = TopicWithCallbacks.create! title: "activerecord", author_name: nil
topic3 = TopicWithCallbacks.create! title: "ar", author_name: nil
topics = TopicWithCallbacks.where(id: [topic1.id, topic2.id])
topics.update!(title: "adequaterecord")
assert_equal TopicWithCallbacks.count, TopicWithCallbacks.topic_count
assert_equal "adequaterecord", topic1.reload.title
assert_equal "adequaterecord", topic2.reload.title
assert_equal "ar", topic3.reload.title
# Testing that the before_update callbacks have run
assert_equal "David", topic1.reload.author_name
assert_equal "David", topic2.reload.author_name
assert_nil topic3.reload.author_name
end
def test_update_all_cares_about_optimistic_locking
david = people(:david)