Permalink
Browse files

Deprecate update_column in favor of update_columns.

Closes #1190
  • Loading branch information...
rafaelfranca committed Jul 24, 2012
1 parent da84ccb commit 2d9e5a26a10e5f83f9b3ac465bd45b2e15a0bc2a
View
@@ -1,5 +1,17 @@
## Rails 4.0.0 (unreleased) ##
+* Deprecate `update_column` method in favor of `update_columns`.
+
+ *Rafael Mendonça França*
+
+* Added an `update_columns` method. This new method updates the given attributes on an object,
+ without calling save, hence skipping validations and callbacks.
+ Example:
+
+ User.first.update_columns({:name => "sebastian", :age => 25}) # => true
+
+ *Sebastian Martinez + Rafael Mendonça França*
+
* Removed `:finder_sql` and `:counter_sql` collection association options. Please
use scopes instead.
@@ -36,7 +36,7 @@ def delete(method = options[:dependent])
when :destroy
target.destroy
when :nullify
- target.update_column(reflection.foreign_key, nil)
+ target.update_columns(reflection.foreign_key => nil)
end
end
end
@@ -204,6 +204,11 @@ def update_attributes!(attributes, options = {})
# Raises an +ActiveRecordError+ when called on new objects, or when the +name+
# attribute is marked as readonly.
def update_column(name, value)
+ msg = "update_column is deprecated and will be removed in 4.1. Please use update_columns. " \
+ "E.g. update_columns(foo: 'bar')"
+
+ ActiveSupport::Deprecation.warn(msg)
+
update_columns(name => value)
end
@@ -243,7 +248,7 @@ def increment(attribute, by = 1)
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def increment!(attribute, by = 1)
- increment(attribute, by).update_column(attribute, self[attribute])
+ increment(attribute, by).update_columns(attribute => self[attribute])
end
# Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
@@ -260,7 +265,7 @@ def decrement(attribute, by = 1)
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def decrement!(attribute, by = 1)
- decrement(attribute, by).update_column(attribute, self[attribute])
+ decrement(attribute, by).update_columns(attribute => self[attribute])
end
# Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
@@ -277,7 +282,7 @@ def toggle(attribute)
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def toggle!(attribute)
- toggle(attribute).update_column(attribute, self[attribute])
+ toggle(attribute).update_columns(attribute => self[attribute])
end
# Reloads the attributes of this object from the database.
@@ -298,12 +298,12 @@ def test_belongs_to_counter_after_update_attributes
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
- def test_belongs_to_counter_when_update_column
+ def test_belongs_to_counter_when_update_columns
topic = Topic.create!(:title => "37s")
topic.replies.create!(:title => "re: 37s", :content => "rails")
assert_equal 1, Topic.find(topic.id)[:replies_count]
- topic.update_column(:content, "rails is wonderfull")
+ topic.update_columns(content: "rails is wonderfull")
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
@@ -582,7 +582,7 @@ def test_update_attributes_after_push_without_duplicate_join_table_rows
project = SpecialProject.create("name" => "Special Project")
assert developer.save
developer.projects << project
- developer.update_column("name", "Bruza")
+ developer.update_columns("name" => "Bruza")
assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
SELECT count(*) FROM developers_projects
WHERE project_id = #{project.id}
@@ -634,7 +634,7 @@ def test_deleting_updates_counter_cache_without_dependent_option
def test_deleting_updates_counter_cache_with_dependent_delete_all
post = posts(:welcome)
- post.update_column(:taggings_with_delete_all_count, post.taggings_count)
+ post.update_columns(taggings_with_delete_all_count: post.taggings_count)
assert_difference "post.reload.taggings_with_delete_all_count", -1 do
post.taggings_with_delete_all.delete(post.taggings_with_delete_all.first)
@@ -643,7 +643,7 @@ def test_deleting_updates_counter_cache_with_dependent_delete_all
def test_deleting_updates_counter_cache_with_dependent_destroy
post = posts(:welcome)
- post.update_column(:taggings_with_destroy_count, post.taggings_count)
+ post.update_columns(taggings_with_destroy_count: post.taggings_count)
assert_difference "post.reload.taggings_with_destroy_count", -1 do
post.taggings_with_destroy.delete(post.taggings_with_destroy.first)
@@ -813,7 +813,7 @@ def test_delete_all_association_with_primary_key_deletes_correct_records
firm = Firm.first
# break the vanilla firm_id foreign key
assert_equal 2, firm.clients.count
- firm.clients.first.update_column(:firm_id, nil)
+ firm.clients.first.update_columns(firm_id: nil)
assert_equal 1, firm.clients(true).count
assert_equal 1, firm.clients_using_primary_key_with_delete_all.count
old_record = firm.clients_using_primary_key_with_delete_all.first
@@ -327,7 +327,7 @@ def test_update_counter_caches_on_delete
def test_update_counter_caches_on_delete_with_dependent_destroy
post = posts(:welcome)
tag = post.tags.create!(:name => 'doomed')
- post.update_column(:tags_with_destroy_count, post.tags.count)
+ post.update_columns(tags_with_destroy_count: post.tags.count)
assert_difference ['post.reload.taggings_count', 'post.reload.tags_with_destroy_count'], -1 do
posts(:welcome).tags_with_destroy.delete(tag)
@@ -337,7 +337,7 @@ def test_update_counter_caches_on_delete_with_dependent_destroy
def test_update_counter_caches_on_delete_with_dependent_nullify
post = posts(:welcome)
tag = post.tags.create!(:name => 'doomed')
- post.update_column(:tags_with_nullify_count, post.tags.count)
+ post.update_columns(tags_with_nullify_count: post.tags.count)
assert_no_difference 'post.reload.taggings_count' do
assert_difference 'post.reload.tags_with_nullify_count', -1 do
@@ -90,12 +90,12 @@ def test_has_one_through_eager_loading_through_polymorphic
def test_has_one_through_with_conditions_eager_loading
# conditions on the through table
assert_equal clubs(:moustache_club), Member.scoped(:includes => :favourite_club).find(@member.id).favourite_club
- memberships(:membership_of_favourite_club).update_column(:favourite, false)
+ memberships(:membership_of_favourite_club).update_columns(favourite: false)
assert_equal nil, Member.scoped(:includes => :favourite_club).find(@member.id).reload.favourite_club
# conditions on the source table
assert_equal clubs(:moustache_club), Member.scoped(:includes => :hairy_club).find(@member.id).hairy_club
- clubs(:moustache_club).update_column(:name, "Association of Clean-Shaven Persons")
+ clubs(:moustache_club).update_columns(name: "Association of Clean-Shaven Persons")
assert_equal nil, Member.scoped(:includes => :hairy_club).find(@member.id).reload.hairy_club
end
@@ -175,7 +175,7 @@ def test_create_polymorphic_has_one_with_scope
def test_delete_polymorphic_has_many_with_delete_all
assert_equal 1, posts(:welcome).taggings.count
- posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDeleteAll'
+ posts(:welcome).taggings.first.update_columns taggable_type: 'PostWithHasManyDeleteAll'
post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
old_count = Tagging.count
@@ -186,7 +186,7 @@ def test_delete_polymorphic_has_many_with_delete_all
def test_delete_polymorphic_has_many_with_destroy
assert_equal 1, posts(:welcome).taggings.count
- posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDestroy'
+ posts(:welcome).taggings.first.update_columns taggable_type: 'PostWithHasManyDestroy'
post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
old_count = Tagging.count
@@ -197,7 +197,7 @@ def test_delete_polymorphic_has_many_with_destroy
def test_delete_polymorphic_has_many_with_nullify
assert_equal 1, posts(:welcome).taggings.count
- posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyNullify'
+ posts(:welcome).taggings.first.update_columns taggable_type: 'PostWithHasManyNullify'
post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
old_count = Tagging.count
@@ -208,7 +208,7 @@ def test_delete_polymorphic_has_many_with_nullify
def test_delete_polymorphic_has_one_with_destroy
assert posts(:welcome).tagging
- posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneDestroy'
+ posts(:welcome).tagging.update_columns taggable_type: 'PostWithHasOneDestroy'
post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
old_count = Tagging.count
@@ -219,7 +219,7 @@ def test_delete_polymorphic_has_one_with_destroy
def test_delete_polymorphic_has_one_with_nullify
assert posts(:welcome).tagging
- posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneNullify'
+ posts(:welcome).tagging.update_columns taggable_type: 'PostWithHasOneNullify'
post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
old_count = Tagging.count
@@ -734,7 +734,7 @@ def test_has_many_with_pluralize_table_names_false
# create dynamic Post models to allow different dependency options
def find_post_with_dependency(post_id, association, association_name, dependency)
class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
- Post.find(post_id).update_column :type, class_name
+ Post.find(post_id).update_columns type: class_name
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
klass.table_name = 'posts'
klass.send(association, association_name, :as => :taggable, :dependent => dependency)
@@ -67,7 +67,7 @@ def test_loading_the_association_target_should_load_most_recent_attributes_for_c
ship = Ship.create!(:name => "The good ship Dollypop")
part = ship.parts.create!(:name => "Mast")
part.mark_for_destruction
- ShipPart.find(part.id).update_column(:name, 'Deck')
+ ShipPart.find(part.id).update_columns(name: 'Deck')
ship.parts.send(:load_target)
assert_equal 'Deck', ship.parts[0].name
end
@@ -176,7 +176,7 @@ def test_save_on_parent_does_not_load_target
david = developers(:david)
assert !david.projects.loaded?
- david.update_column(:created_at, Time.now)
+ david.update_columns(created_at: Time.now)
assert !david.projects.loaded?
end
@@ -609,7 +609,7 @@ def test_non_valid_identifier_column_name
assert_equal 'value', weird.send('a$b')
assert_equal 'value', weird.read_attribute('a$b')
- weird.update_column('a$b', 'value2')
+ weird.update_columns('a$b' => 'value2')
weird.reload
assert_equal 'value2', weird.send('a$b')
assert_equal 'value2', weird.read_attribute('a$b')
@@ -1896,7 +1896,7 @@ def test_cache_key_format_for_existing_record_with_updated_at
def test_cache_key_format_for_existing_record_with_nil_updated_at
dev = Developer.first
- dev.update_column(:updated_at, nil)
+ dev.update_columns(updated_at: nil)
assert_match(/\/#{dev.id}$/, dev.cache_key)
end
@@ -331,8 +331,8 @@ def test_should_count_scoped_select
def test_should_count_scoped_select_with_options
Account.update_all("credit_limit = NULL")
- Account.last.update_column('credit_limit', 49)
- Account.first.update_column('credit_limit', 51)
+ Account.last.update_columns('credit_limit' => 49)
+ Account.first.update_columns('credit_limit' => 51)
assert_equal 1, Account.scoped(:select => "credit_limit").where('credit_limit >= 50').count
end
@@ -424,7 +424,7 @@ def test_save_should_not_save_serialized_attribute_with_partial_updates_if_not_p
with_partial_updates(Topic) do
Topic.create!(:author_name => 'Bill', :content => {:a => "a"})
topic = Topic.select('id, author_name').first
- topic.update_column :author_name, 'John'
+ topic.update_columns author_name: 'John'
topic = Topic.first
assert_not_nil topic.content
end
@@ -377,22 +377,21 @@ def test_update_attribute_does_not_choke_on_nil
def test_update_column
topic = Topic.find(1)
- topic.update_column("approved", true)
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ topic.update_column("approved", true)
+ end
assert topic.approved?
topic.reload
assert topic.approved?
-
- topic.update_column(:approved, false)
- assert !topic.approved?
- topic.reload
- assert !topic.approved?
end
def test_update_column_should_not_use_setter_method
dev = Developer.find(1)
dev.instance_eval { def salary=(value); write_attribute(:salary, value * 2); end }
- dev.update_column(:salary, 80000)
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ dev.update_column(:salary, 80000)
+ end
assert_equal 80000, dev.salary
dev.reload
@@ -401,45 +400,65 @@ def test_update_column_should_not_use_setter_method
def test_update_column_should_raise_exception_if_new_record
topic = Topic.new
- assert_raises(ActiveRecord::ActiveRecordError) { topic.update_column("approved", false) }
+ assert_raises(ActiveRecord::ActiveRecordError) do
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ topic.update_column("approved", false)
+ end
+ end
end
def test_update_column_should_not_leave_the_object_dirty
topic = Topic.find(1)
- topic.update_column("content", "Have a nice day")
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ topic.update_column("content", "Have a nice day")
+ end
topic.reload
- topic.update_column(:content, "You too")
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ topic.update_column(:content, "You too")
+ end
assert_equal [], topic.changed
topic.reload
- topic.update_column("content", "Have a nice day")
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ topic.update_column("content", "Have a nice day")
+ end
assert_equal [], topic.changed
end
def test_update_column_with_model_having_primary_key_other_than_id
minivan = Minivan.find('m1')
new_name = 'sebavan'
- minivan.update_column(:name, new_name)
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ minivan.update_column(:name, new_name)
+ end
assert_equal new_name, minivan.name
end
def test_update_column_for_readonly_attribute
minivan = Minivan.find('m1')
prev_color = minivan.color
- assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_column(:color, 'black') }
+ assert_raises(ActiveRecord::ActiveRecordError) do
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ minivan.update_column(:color, 'black')
+ end
+ end
assert_equal prev_color, minivan.color
end
def test_update_column_should_not_modify_updated_at
developer = Developer.find(1)
prev_month = Time.now.prev_month
- developer.update_column(:updated_at, prev_month)
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ developer.update_column(:updated_at, prev_month)
+ end
assert_equal prev_month, developer.updated_at
- developer.update_column(:salary, 80001)
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ developer.update_column(:salary, 80001)
+ end
assert_equal prev_month, developer.updated_at
developer.reload
@@ -448,9 +467,11 @@ def test_update_column_should_not_modify_updated_at
def test_update_column_with_one_changed_and_one_updated
t = Topic.order('id').limit(1).first
- title, author_name = t.title, t.author_name
+ author_name = t.author_name
t.author_name = 'John'
- t.update_column(:title, 'super_title')
+ assert_deprecated "update_column is deprecated and will be removed in 4.1. Please use update_columns. E.g. update_columns(foo: 'bar')" do
+ t.update_column(:title, 'super_title')
+ end
assert_equal 'John', t.author_name
assert_equal 'super_title', t.title
assert t.changed?, "topic should have changed"
Oops, something went wrong.

0 comments on commit 2d9e5a2

Please sign in to comment.