Skip to content
This repository
Browse code

Remove update_attribute.

Historically, update_attribute and update_attributes are similar, but
with one big difference: update_attribute does not run validations.
These two methods are really easy to confuse given their similar
names. Therefore, update_attribute is being removed in favor of
update_column.

See the thread on rails-core here:
https://groups.google.com/forum/?fromgroups#!topic/rubyonrails-core/BWPUTK7WvYA
  • Loading branch information...
commit a7f4b0a1231bf3c65db2ad4066da78c3da5ffb01 1 parent 99c9d18
Steve Klabnik authored June 14, 2012
2  activerecord/lib/active_record/associations/has_one_association.rb
@@ -36,7 +36,7 @@ def delete(method = options[:dependent])
36 36
             when :destroy
37 37
               target.destroy
38 38
             when :nullify
39  
-              target.update_attribute(reflection.foreign_key, nil)
  39
+              target.update_column(reflection.foreign_key, nil)
40 40
           end
41 41
         end
42 42
       end
4  activerecord/lib/active_record/migration.rb
@@ -238,7 +238,7 @@ def initialize
238 238
   #       add_column :people, :salary, :integer
239 239
   #       Person.reset_column_information
240 240
   #       Person.all.each do |p|
241  
-  #         p.update_attribute :salary, SalaryCalculator.compute(p)
  241
+  #         p.update_column :salary, SalaryCalculator.compute(p)
242 242
   #       end
243 243
   #     end
244 244
   #   end
@@ -258,7 +258,7 @@ def initialize
258 258
   #     ...
259 259
   #     say_with_time "Updating salaries..." do
260 260
   #       Person.all.each do |p|
261  
-  #         p.update_attribute :salary, SalaryCalculator.compute(p)
  261
+  #         p.update_column :salary, SalaryCalculator.compute(p)
262 262
   #       end
263 263
   #     end
264 264
   #     ...
21  activerecord/lib/active_record/persistence.rb
@@ -167,21 +167,6 @@ def becomes(klass)
167 167
       became
168 168
     end
169 169
 
170  
-    # Updates a single attribute and saves the record.
171  
-    # This is especially useful for boolean flags on existing records. Also note that
172  
-    #
173  
-    # * Validation is skipped.
174  
-    # * Callbacks are invoked.
175  
-    # * updated_at/updated_on column is updated if that column is available.
176  
-    # * Updates all the attributes that are dirty in this object.
177  
-    #
178  
-    def update_attribute(name, value)
179  
-      name = name.to_s
180  
-      verify_readonly_attribute(name)
181  
-      send("#{name}=", value)
182  
-      save(:validate => false)
183  
-    end
184  
-
185 170
     # Updates a single attribute of an object, without calling save.
186 171
     #
187 172
     # * Validation is skipped.
@@ -240,7 +225,7 @@ def increment(attribute, by = 1)
240 225
     # Saving is not subjected to validation checks. Returns +true+ if the
241 226
     # record could be saved.
242 227
     def increment!(attribute, by = 1)
243  
-      increment(attribute, by).update_attribute(attribute, self[attribute])
  228
+      increment(attribute, by).update_column(attribute, self[attribute])
244 229
     end
245 230
 
246 231
     # Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
@@ -257,7 +242,7 @@ def decrement(attribute, by = 1)
257 242
     # Saving is not subjected to validation checks. Returns +true+ if the
258 243
     # record could be saved.
259 244
     def decrement!(attribute, by = 1)
260  
-      decrement(attribute, by).update_attribute(attribute, self[attribute])
  245
+      decrement(attribute, by).update_column(attribute, self[attribute])
261 246
     end
262 247
 
263 248
     # Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
@@ -274,7 +259,7 @@ def toggle(attribute)
274 259
     # Saving is not subjected to validation checks. Returns +true+ if the
275 260
     # record could be saved.
276 261
     def toggle!(attribute)
277  
-      toggle(attribute).update_attribute(attribute, self[attribute])
  262
+      toggle(attribute).update_column(attribute, self[attribute])
278 263
     end
279 264
 
280 265
     # Reloads the attributes of this object from the database.
2  activerecord/test/cases/base_test.rb
@@ -1935,7 +1935,7 @@ def test_cache_key_format_for_existing_record_with_updated_at
1935 1935
 
1936 1936
   def test_cache_key_format_for_existing_record_with_nil_updated_at
1937 1937
     dev = Developer.first
1938  
-    dev.update_attribute(:updated_at, nil)
  1938
+    dev.update_column(:updated_at, nil)
1939 1939
     assert_match(/\/#{dev.id}$/, dev.cache_key)
1940 1940
   end
1941 1941
 
2  activerecord/test/cases/dirty_test.rb
@@ -498,7 +498,7 @@ def test_previous_changes
498 498
     assert !pirate.previous_changes.key?('created_on')
499 499
 
500 500
     pirate = Pirate.find_by_catchphrase("Ahoy!")
501  
-    pirate.update_attribute(:catchphrase, "Ninjas suck!")
  501
+    pirate.update_column(:catchphrase, "Ninjas suck!")
502 502
 
503 503
     assert_equal 2, pirate.previous_changes.size
504 504
     assert_equal ["Ahoy!", "Ninjas suck!"], pirate.previous_changes['catchphrase']
63  activerecord/test/cases/persistence_test.rb
@@ -371,71 +371,10 @@ def test_destroy_record_with_associations
371 371
     assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
372 372
   end
373 373
 
374  
-  def test_update_attribute
375  
-    assert !Topic.find(1).approved?
376  
-    Topic.find(1).update_attribute("approved", true)
377  
-    assert Topic.find(1).approved?
378  
-
379  
-    Topic.find(1).update_attribute(:approved, false)
380  
-    assert !Topic.find(1).approved?
381  
-  end
382  
-
383 374
   def test_update_attribute_does_not_choke_on_nil
384 375
     assert Topic.find(1).update_attributes(nil)
385 376
   end
386 377
 
387  
-  def test_update_attribute_for_readonly_attribute
388  
-    minivan = Minivan.find('m1')
389  
-    assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_attribute(:color, 'black') }
390  
-  end
391  
-
392  
-  # This test is correct, but it is hard to fix it since
393  
-  # update_attribute trigger simply call save! that triggers
394  
-  # all callbacks.
395  
-  # def test_update_attribute_with_one_changed_and_one_updated
396  
-  #   t = Topic.order('id').limit(1).first
397  
-  #   title, author_name = t.title, t.author_name
398  
-  #   t.author_name = 'John'
399  
-  #   t.update_attribute(:title, 'super_title')
400  
-  #   assert_equal 'John', t.author_name
401  
-  #   assert_equal 'super_title', t.title
402  
-  #   assert t.changed?, "topic should have changed"
403  
-  #   assert t.author_name_changed?, "author_name should have changed"
404  
-  #   assert !t.title_changed?, "title should not have changed"
405  
-  #   assert_nil t.title_change, 'title change should be nil'
406  
-  #   assert_equal ['author_name'], t.changed
407  
-  #
408  
-  #   t.reload
409  
-  #   assert_equal 'David', t.author_name
410  
-  #   assert_equal 'super_title', t.title
411  
-  # end
412  
-
413  
-  def test_update_attribute_with_one_updated
414  
-    t = Topic.first
415  
-    t.update_attribute(:title, 'super_title')
416  
-    assert_equal 'super_title', t.title
417  
-    assert !t.changed?, "topic should not have changed"
418  
-    assert !t.title_changed?, "title should not have changed"
419  
-    assert_nil t.title_change, 'title change should be nil'
420  
-
421  
-    t.reload
422  
-    assert_equal 'super_title', t.title
423  
-  end
424  
-
425  
-  def test_update_attribute_for_updated_at_on
426  
-    developer = Developer.find(1)
427  
-    prev_month = Time.now.prev_month
428  
-
429  
-    developer.update_attribute(:updated_at, prev_month)
430  
-    assert_equal prev_month, developer.updated_at
431  
-
432  
-    developer.update_attribute(:salary, 80001)
433  
-    assert_not_equal prev_month, developer.updated_at
434  
-
435  
-    developer.reload
436  
-    assert_not_equal prev_month, developer.updated_at
437  
-  end
438  
-
439 378
   def test_update_column
440 379
     topic = Topic.find(1)
441 380
     topic.update_column("approved", true)
@@ -467,7 +406,7 @@ def test_update_column_should_raise_exception_if_new_record
467 406
 
468 407
   def test_update_column_should_not_leave_the_object_dirty
469 408
     topic = Topic.find(1)
470  
-    topic.update_attribute("content", "Have a nice day")
  409
+    topic.update_column("content", "Have a nice day")
471 410
 
472 411
     topic.reload
473 412
     topic.update_column(:content, "You too")
4  activerecord/test/cases/timestamp_test.rb
@@ -11,7 +11,7 @@ class TimestampTest < ActiveRecord::TestCase
11 11
 
12 12
   def setup
13 13
     @developer = Developer.first
14  
-    @developer.update_attribute(:updated_at, Time.now.prev_month)
  14
+    @developer.update_column(:updated_at, Time.now.prev_month)
15 15
     @previously_updated_at = @developer.updated_at
16 16
   end
17 17
 
@@ -133,7 +133,7 @@ def test_touching_a_record_with_a_belongs_to_that_uses_a_counter_cache_should_up
133 133
 
134 134
     pet = Pet.first
135 135
     owner = pet.owner
136  
-    owner.update_attribute(:happy_at, 3.days.ago)
  136
+    owner.update_column(:happy_at, 3.days.ago)
137 137
     previously_owner_updated_at = owner.updated_at
138 138
 
139 139
     pet.name = "I'm a parrot"

4 notes on commit a7f4b0a

adsummos

can't we at least deprecate update_attribute before removing it?

Steve Klabnik
Collaborator

@adsummos it is deprecated in 3.2.x.

Kornelius Kalnbach

Smart move.

Vieenay Siingh

wow.

Please sign in to comment.
Something went wrong with that request. Please try again.