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)