aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2012-12-06 23:09:11 -0200
committerCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2012-12-06 23:49:53 -0200
commita3c3cfdd0ebba26bb9dfc0bfd4e23a5f336730c0 (patch)
treec2a9ce17e80fab8246b005aced974a4d45907d29
parentd70539c1ec4c1f615bb359468b7b0c58276bf71b (diff)
downloadrails-a3c3cfdd0ebba26bb9dfc0bfd4e23a5f336730c0.tar.gz
rails-a3c3cfdd0ebba26bb9dfc0bfd4e23a5f336730c0.tar.bz2
rails-a3c3cfdd0ebba26bb9dfc0bfd4e23a5f336730c0.zip
Unscope update_column(s) query to ignore default scope
When applying default_scope to a class with a where clause, using update_column(s) could generate a query that would not properly update the record due to the where clause from the default_scope being applied to the update query. class User < ActiveRecord::Base default_scope where(active: true) end user = User.first user.active = false user.save! user.update_column(:active, true) # => false In this situation we want to skip the default_scope clause and just update the record based on the primary key. With this change: user.update_column(:active, true) # => true Backport of #8436 fix. Conflicts: activerecord/CHANGELOG.md activerecord/lib/active_record/persistence.rb activerecord/test/cases/persistence_test.rb
-rw-r--r--activerecord/CHANGELOG.md26
-rw-r--r--activerecord/lib/active_record/persistence.rb2
-rw-r--r--activerecord/test/cases/persistence_test.rb8
3 files changed, 35 insertions, 1 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 66c3222a25..f12094ab1e 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,31 @@
## Rails 3.2.10 (unreleased)
+* Unscope `update_column(s)` query to ignore default scope.
+
+ When applying `default_scope` to a class with a where clause, using
+ `update_column(s)` could generate a query that would not properly update
+ the record due to the where clause from the `default_scope` being applied
+ to the update query.
+
+ class User < ActiveRecord::Base
+ default_scope where(active: true)
+ end
+
+ user = User.first
+ user.active = false
+ user.save!
+
+ user.update_column(:active, true) # => false
+
+ In this situation we want to skip the default_scope clause and just
+ update the record based on the primary key. With this change:
+
+ user.update_column(:active, true) # => true
+
+ Backport of #8436 fix.
+
+ *Carlos Antonio da Silva*
+
* Fix performance problem with primary_key method in PostgreSQL adapter when having many schemas.
Uses pg_constraint table instead of pg_depend table which has many records in general.
Fix #8414
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index fd3380a53c..36b6b5fce2 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -194,7 +194,7 @@ module ActiveRecord
raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
raise ActiveRecordError, "can not update on a new record object" unless persisted?
- updated_count = self.class.update_all({ name => value }, self.class.primary_key => id)
+ updated_count = self.class.unscoped.update_all({ name => value }, self.class.primary_key => id)
raw_write_attribute(name, value)
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index a35cb3c4a5..00dc1f6d72 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -519,6 +519,14 @@ class PersistencesTest < ActiveRecord::TestCase
assert return_value
end
+ def test_update_column_with_default_scope
+ developer = DeveloperCalledDavid.first
+ developer.name = 'John'
+ developer.save!
+
+ assert developer.update_column(:name, 'Will'), 'did not update record due to default scope'
+ end
+
def test_update_attributes
topic = Topic.find(1)
assert !topic.approved?