diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 97c36a6..8774ab2 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -818,7 +818,7 @@ module ActiveRecord #:nodoc: # # * +updates+ - A string, array, or hash representing the SET part of an SQL statement. # * +conditions+ - A string, array, or hash representing the WHERE part of an SQL statement. See conditions in the intro. - # * +options+ - Additional options are :limit and :order, see the examples for usage. + # * +options+ - Additional options are :limit, :order and :joins, see the examples for usage. # # ==== Examples # @@ -833,12 +833,18 @@ module ActiveRecord #:nodoc: # # # Update all books that match our conditions, but limit it to 5 ordered by date # Book.update_all "author = 'David'", "title LIKE '%Rails%'", :order => 'created_at', :limit => 5 + # + # # Update all books that match our conditions + # Book.update_all "rating = 'high'", "title LIKE '%Rails%' and authors.name = 'David'", :joins => :authors def update_all(updates, conditions = nil, options = {}) - sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} " + sql = "UPDATE #{quoted_table_name} " scope = scope(:find) select_sql = "" + + add_joins!(select_sql, options[:joins], scope) if (scope && scope[:joins]) || options[:joins] + select_sql.concat("SET #{sanitize_sql_for_assignment(updates)} ") add_conditions!(select_sql, conditions, scope) if options.has_key?(:limit) || (scope && scope[:limit]) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 7ca2807..65e0f7c 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -661,6 +661,23 @@ class BasicsTest < ActiveRecord::TestCase assert_nil Topic.find(1).content end + def test_update_all_on_named_scope_with_joins + assert_equal Post.with_special_comments.count('posts.id', :distinct => true), Post.with_special_comments.update_all("posts.body = 'bulky'") + Post.with_special_comments.each do |post| + assert_equal post.body, 'bulky' + end + assert_equal Post.count(:conditions => {:body => 'bulky'}), Post.with_special_comments.count('posts.id', :distinct => true) + end + + def test_update_all_with_joins + assert_equal Post.count('posts.id', :distinct => true, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'}}), + Post.update_all("posts.body = 'bulky'", {:comments => {:type => 'SpecialComment'}}, {:joins => :comments}) + Post.find(:all, :conditions => {:comments => {:type => 'SpecialComment'}}, :joins => :comments).each do |post| + assert_equal post.body, 'bulky' + end + assert_equal Post.count(:conditions => {:body => 'bulky'}), Post.count('posts.id', :distinct => true, :conditions => {:comments => {:type => 'SpecialComment'}}, :joins => :comments) + end + def test_update_all_with_hash assert_not_nil Topic.find(1).last_read assert_equal Topic.count, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)