aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2017-10-16 01:33:40 +0900
committerRyuta Kamizono <kamipo@gmail.com>2017-11-06 04:04:54 +0900
commit8a2ee3d8c6921ce34e597658e3f2b43b41423d1d (patch)
tree4e9a337567e3de1b18901b4754a589652451c1ba /activerecord
parente3a295664681ea0480a9c95f6bfc776a113ff926 (diff)
downloadrails-8a2ee3d8c6921ce34e597658e3f2b43b41423d1d.tar.gz
rails-8a2ee3d8c6921ce34e597658e3f2b43b41423d1d.tar.bz2
rails-8a2ee3d8c6921ce34e597658e3f2b43b41423d1d.zip
Ensure `apply_join_dependency` for `update_all` and `delete_all` if eager-loading is needed
If a relation has eager-loading values, `count` and `exists?` works properly, but `update_all` and `delete_all` doesn't work due to missing `apply_join_dependency`. It should be applied to work consistently. Fixes #28863.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/relation.rb10
-rw-r--r--activerecord/test/cases/persistence_test.rb49
2 files changed, 40 insertions, 19 deletions
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 997cfe4b5e..7615fb6ee9 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -359,6 +359,11 @@ module ActiveRecord
def update_all(updates)
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
+ if eager_loading?
+ relation = apply_join_dependency
+ return relation.update_all(updates)
+ end
+
stmt = Arel::UpdateManager.new
stmt.set Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates))
@@ -423,6 +428,11 @@ module ActiveRecord
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
end
+ if eager_loading?
+ relation = apply_join_dependency
+ return relation.delete_all
+ end
+
stmt = Arel::DeleteManager.new
stmt.from(table)
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 6cbe18cc8c..f088c064f5 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -94,27 +94,31 @@ class PersistenceTest < ActiveRecord::TestCase
end
def test_delete_all_with_joins_and_where_part_is_hash
- where_args = { toys: { name: "Bone" } }
- count = Pet.joins(:toys).where(where_args).count
+ pets = Pet.joins(:toys).where(toys: { name: "Bone" })
- assert_equal count, 1
- assert_equal count, Pet.joins(:toys).where(where_args).delete_all
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.delete_all
+ end
+
+ def test_delete_all_with_joins_and_where_part_is_not_hash
+ pets = Pet.joins(:toys).where("toys.name = ?", "Bone")
+
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.delete_all
end
def test_delete_all_with_left_joins
- where_args = { toys: { name: "Bone" } }
- count = Pet.left_joins(:toys).where(where_args).count
+ pets = Pet.left_joins(:toys).where(toys: { name: "Bone" })
- assert_equal count, 1
- assert_equal count, Pet.left_joins(:toys).where(where_args).delete_all
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.delete_all
end
- def test_delete_all_with_joins_and_where_part_is_not_hash
- where_args = ["toys.name = ?", "Bone"]
- count = Pet.joins(:toys).where(where_args).count
+ def test_delete_all_with_includes
+ pets = Pet.includes(:toys).where(toys: { name: "Bone" })
- assert_equal count, 1
- assert_equal count, Pet.joins(:toys).where(where_args).delete_all
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.delete_all
end
def test_increment_attribute
@@ -496,17 +500,24 @@ class PersistenceTest < ActiveRecord::TestCase
end
def test_update_all_with_joins
- where_args = { toys: { name: "Bone" } }
- count = Pet.left_joins(:toys).where(where_args).count
+ pets = Pet.joins(:toys).where(toys: { name: "Bone" })
- assert_equal count, Pet.joins(:toys).where(where_args).update_all(name: "Bob")
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.update_all(name: "Bob")
end
def test_update_all_with_left_joins
- where_args = { toys: { name: "Bone" } }
- count = Pet.left_joins(:toys).where(where_args).count
+ pets = Pet.left_joins(:toys).where(toys: { name: "Bone" })
+
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.update_all(name: "Bob")
+ end
+
+ def test_update_all_with_includes
+ pets = Pet.includes(:toys).where(toys: { name: "Bone" })
- assert_equal count, Pet.left_joins(:toys).where(where_args).update_all(name: "Bob")
+ assert_equal true, pets.exists?
+ assert_equal pets.count, pets.update_all(name: "Bob")
end
def test_update_all_with_non_standard_table_name