Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
  • Loading branch information...
commit a3c3cfdd0ebba26bb9dfc0bfd4e23a5f336730c0 1 parent d70539c
@carlosantoniodasilva carlosantoniodasilva authored
View
26 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
View
2  activerecord/lib/active_record/persistence.rb
@@ -194,7 +194,7 @@ def update_column(name, value)
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)
View
8 activerecord/test/cases/persistence_test.rb
@@ -519,6 +519,14 @@ def test_update_column_should_return_correct_value
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?
Please sign in to comment.
Something went wrong with that request. Please try again.