Permalink
Browse files

Move update and update_all to Relation

  • Loading branch information...
1 parent 93956a1 commit 8d31c9f3a0c69ce7e8f905a4e75177037bbbcad5 @lifo lifo committed Jan 20, 2010
Showing with 65 additions and 70 deletions.
  1. +1 −70 activerecord/lib/active_record/base.rb
  2. +64 −0 activerecord/lib/active_record/relation.rb
View
71 activerecord/lib/active_record/base.rb
@@ -556,7 +556,7 @@ def colorize_logging(*args)
end
alias :colorize_logging= :colorize_logging
- delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :to => :scoped
+ delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
delegate :select, :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :to => :scoped
delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped
@@ -619,75 +619,6 @@ def create(attributes = nil, &block)
end
end
- # Updates an object (or multiple objects) and saves it to the database, if validations pass.
- # The resulting object is returned whether the object was saved successfully to the database or not.
- #
- # ==== Parameters
- #
- # * +id+ - This should be the id or an array of ids to be updated.
- # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
- #
- # ==== Examples
- #
- # # Updating one record:
- # Person.update(15, :user_name => 'Samuel', :group => 'expert')
- #
- # # Updating multiple records:
- # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
- # Person.update(people.keys, people.values)
- def update(id, attributes)
- if id.is_a?(Array)
- idx = -1
- id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
- else
- object = find(id)
- object.update_attributes(attributes)
- object
- end
- end
-
- # Updates all records with details given if they match a set of conditions supplied, limits and order can
- # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
- # database. It does not instantiate the involved models and it does not trigger Active Record callbacks
- # or validations.
- #
- # ==== Parameters
- #
- # * +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 <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage.
- #
- # ==== Examples
- #
- # # Update all customers with the given attributes
- # Customer.update_all :wants_email => true
- #
- # # Update all books with 'Rails' in their title
- # Book.update_all "author = 'David'", "title LIKE '%Rails%'"
- #
- # # Update all avatars migrated more than a week ago
- # Avatar.update_all ['migrated_at = ?', Time.now.utc], ['migrated_at > ?', 1.week.ago]
- #
- # # 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
- def update_all(updates, conditions = nil, options = {})
- relation = unscoped
-
- relation = relation.where(conditions) if conditions
- relation = relation.limit(options[:limit]) if options[:limit].present?
- relation = relation.order(options[:order]) if options[:order].present?
-
- if current_scoped_methods && current_scoped_methods.limit_value.present? && current_scoped_methods.order_values.present?
- # Only take order from scope if limit is also provided by scope, this
- # is useful for updating a has_many association with a limit.
- relation = current_scoped_methods.merge(relation) if current_scoped_methods
- else
- relation = current_scoped_methods.except(:limit, :order).merge(relation) if current_scoped_methods
- end
-
- relation.arel.update(sanitize_sql_for_assignment(updates))
- end
-
# Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
# The use of this method should be restricted to complicated SQL queries that can't be executed
# using the ActiveRecord::Calculations class methods. Look into those before using this.
View
64 activerecord/lib/active_record/relation.rb
@@ -84,6 +84,70 @@ def many?
end
end
+ # Updates all records with details given if they match a set of conditions supplied, limits and order can
+ # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
+ # database. It does not instantiate the involved models and it does not trigger Active Record callbacks
+ # or validations.
+ #
+ # ==== Parameters
+ #
+ # * +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 <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage.
+ #
+ # ==== Examples
+ #
+ # # Update all customers with the given attributes
+ # Customer.update_all :wants_email => true
+ #
+ # # Update all books with 'Rails' in their title
+ # Book.update_all "author = 'David'", "title LIKE '%Rails%'"
+ #
+ # # Update all avatars migrated more than a week ago
+ # Avatar.update_all ['migrated_at = ?', Time.now.utc], ['migrated_at > ?', 1.week.ago]
+ #
+ # # 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
+ def update_all(updates, conditions = nil, options = {})
+ if conditions || options.present?
+ where(conditions).apply_finder_options(options.slice(:limit, :order)).update_all(updates)
+ else
+ # Apply limit and order only if they're both present
+ if @limit_value.present? == @order_values.present?
+ arel.update(@klass.send(:sanitize_sql_for_assignment, updates))
+ else
+ except(:limit, :order).update_all(updates)
+ end
+ end
+ end
+
+ # Updates an object (or multiple objects) and saves it to the database, if validations pass.
+ # The resulting object is returned whether the object was saved successfully to the database or not.
+ #
+ # ==== Parameters
+ #
+ # * +id+ - This should be the id or an array of ids to be updated.
+ # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
+ #
+ # ==== Examples
+ #
+ # # Updating one record:
+ # Person.update(15, :user_name => 'Samuel', :group => 'expert')
+ #
+ # # Updating multiple records:
+ # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
+ # Person.update(people.keys, people.values)
+ def update(id, attributes)
+ if id.is_a?(Array)
+ idx = -1
+ id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
+ else
+ object = find(id)
+ object.update_attributes(attributes)
+ object
+ end
+ end
+
# Destroys the records matching +conditions+ by instantiating each
# record and calling its +destroy+ method. Each object's callbacks are
# executed (including <tt>:dependent</tt> association options and

0 comments on commit 8d31c9f

Please sign in to comment.