From 89828a405254bca8cf65259c54990dfe1921326d Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Thu, 14 Mar 2013 01:19:27 +0400 Subject: When we pass id to update_attributes it will try to set new id for that record --- activerecord/CHANGELOG.md | 7 +++++++ activerecord/lib/active_record/attribute_methods.rb | 2 +- activerecord/lib/active_record/persistence.rb | 2 +- activerecord/test/cases/persistence_test.rb | 9 +++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 771f1333f0..4a6e79c68e 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,4 +1,11 @@ ## Rails 4.0.0 (unreleased) ## +* After extraction of mass-assignment attributes (which protects [id, type] + by default) we can pass id to update_attributes and it will update + another record because id will be used in where statement. We never have + to change id in where statement because we try to set/replace fields for + already loaded record but we have to try to set new id for that record. + + *Dmitry Vorotilin* * Models with multiple counter cache associations now update correctly on destroy. See #7706. diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index aa92343f76..769e005c8f 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -348,7 +348,7 @@ module ActiveRecord # Filters the primary keys and readonly attributes from the attribute names. def attributes_for_update(attribute_names) attribute_names.select do |name| - column_for_attribute(name) && !pk_attribute?(name) && !readonly_attribute?(name) + column_for_attribute(name) && !readonly_attribute?(name) end end diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index b25d0601cb..f881778591 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -443,7 +443,7 @@ module ActiveRecord real_column = db_columns_with_values[i].first bind_attrs[column] = klass.connection.substitute_at(real_column, i) end - stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.compile_update(bind_attrs) + stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id_was)).arel.compile_update(bind_attrs) klass.connection.update stmt, 'SQL', db_columns_with_values end end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index b936cca875..a29189df05 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -661,6 +661,15 @@ class PersistencesTest < ActiveRecord::TestCase topic.reload assert !topic.approved? assert_equal "The First Topic", topic.title + + assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do + topic.update_attributes(id: 3, title: "Hm is it possible?") + end + assert_not_equal "Hm is it possible?", Topic.find(3).title + + topic.update_attributes(id: 1234) + assert_nothing_raised { topic.reload } + assert_equal topic.title, Topic.find(1234).title end def test_update! -- cgit v1.2.3