aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rwxr-xr-xactiverecord/lib/active_record/base.rb232
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb2
-rw-r--r--activerecord/lib/active_record/named_scope.rb2
-rw-r--r--activerecord/lib/active_record/relation.rb172
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb44
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb12
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb14
7 files changed, 220 insertions, 258 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 8f2ea10206..bc1b0bde31 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -556,7 +556,7 @@ module ActiveRecord #:nodoc:
end
alias :colorize_logging= :colorize_logging
- delegate :find, :first, :last, :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
@@ -586,40 +586,6 @@ module ActiveRecord #:nodoc:
connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
end
- # Returns true if a record exists in the table that matches the +id+ or
- # conditions given, or false otherwise. The argument can take five forms:
- #
- # * Integer - Finds the record with this primary key.
- # * String - Finds the record with a primary key corresponding to this
- # string (such as <tt>'5'</tt>).
- # * Array - Finds the record that matches these +find+-style conditions
- # (such as <tt>['color = ?', 'red']</tt>).
- # * Hash - Finds the record that matches these +find+-style conditions
- # (such as <tt>{:color => 'red'}</tt>).
- # * No args - Returns false if the table is empty, true otherwise.
- #
- # For more information about specifying conditions as a Hash or Array,
- # see the Conditions section in the introduction to ActiveRecord::Base.
- #
- # Note: You can't pass in a condition as a string (like <tt>name =
- # 'Jamie'</tt>), since it would be sanitized and then queried against
- # the primary key column, like <tt>id = 'name = \'Jamie\''</tt>.
- #
- # ==== Examples
- # Person.exists?(5)
- # Person.exists?('5')
- # Person.exists?(:name => "David")
- # Person.exists?(['name LIKE ?', "%#{query}%"])
- # Person.exists?
- def exists?(id_or_conditions = nil)
- case id_or_conditions
- when Array, Hash
- where(id_or_conditions).exists?
- else
- scoped.exists?(id_or_conditions)
- end
- end
-
# Creates 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.
#
@@ -653,177 +619,6 @@ module ActiveRecord #:nodoc:
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
-
- # Deletes the row with a primary key matching the +id+ argument, using a
- # SQL +DELETE+ statement, and returns the number of rows deleted. Active
- # Record objects are not instantiated, so the object's callbacks are not
- # executed, including any <tt>:dependent</tt> association options or
- # Observer methods.
- #
- # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
- #
- # Note: Although it is often much faster than the alternative,
- # <tt>#destroy</tt>, skipping callbacks might bypass business logic in
- # your application that ensures referential integrity or performs other
- # essential jobs.
- #
- # ==== Examples
- #
- # # Delete a single row
- # Todo.delete(1)
- #
- # # Delete multiple rows
- # Todo.delete([2,3,4])
- def delete(id_or_array)
- scoped.delete(id_or_array)
- end
-
- # Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
- # therefore all callbacks and filters are fired off before the object is deleted. This method is
- # less efficient than ActiveRecord#delete but allows cleanup methods and other actions to be run.
- #
- # This essentially finds the object (or multiple objects) with the given id, creates a new object
- # from the attributes, and then calls destroy on it.
- #
- # ==== Parameters
- #
- # * +id+ - Can be either an Integer or an Array of Integers.
- #
- # ==== Examples
- #
- # # Destroy a single object
- # Todo.destroy(1)
- #
- # # Destroy multiple objects
- # todos = [1,2,3]
- # Todo.destroy(todos)
- def destroy(id)
- if id.is_a?(Array)
- id.map { |one_id| destroy(one_id) }
- else
- find(id).destroy
- 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.update(sanitize_sql_for_assignment(updates))
- 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
- # +before_destroy+/+after_destroy+ Observer methods). Returns the
- # collection of objects that were destroyed; each will be frozen, to
- # reflect that no changes should be made (since they can't be
- # persisted).
- #
- # Note: Instantiation, callback execution, and deletion of each
- # record can be time consuming when you're removing many records at
- # once. It generates at least one SQL +DELETE+ query per record (or
- # possibly more, to enforce your callbacks). If you want to delete many
- # rows quickly, without concern for their associations or callbacks, use
- # +delete_all+ instead.
- #
- # ==== Parameters
- #
- # * +conditions+ - A string, array, or hash that specifies which records
- # to destroy. If omitted, all records are destroyed. See the
- # Conditions section in the introduction to ActiveRecord::Base for
- # more information.
- #
- # ==== Examples
- #
- # Person.destroy_all("last_login < '2004-04-04'")
- # Person.destroy_all(:status => "inactive")
- def destroy_all(conditions = nil)
- where(conditions).destroy_all
- end
-
- # Deletes the records matching +conditions+ without instantiating the records first, and hence not
- # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that
- # goes straight to the database, much more efficient than +destroy_all+. Be careful with relations
- # though, in particular <tt>:dependent</tt> rules defined on associations are not honored. Returns
- # the number of rows affected.
- #
- # ==== Parameters
- #
- # * +conditions+ - Conditions are specified the same way as with +find+ method.
- #
- # ==== Example
- #
- # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
- # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
- #
- # Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent
- # associations or call your <tt>before_*</tt> or +after_destroy+ callbacks, use the +destroy_all+ method instead.
- def delete_all(conditions = nil)
- where(conditions).delete_all
- 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.
@@ -1111,6 +906,10 @@ module ActiveRecord #:nodoc:
reset_table_name
end
+ def quoted_table_name
+ @quoted_table_name ||= connection.quote_table_name(table_name)
+ end
+
def reset_table_name #:nodoc:
base = base_class
@@ -1128,6 +927,7 @@ module ActiveRecord #:nodoc:
name = "#{table_name_prefix}#{contained}#{undecorated_table_name(base.name)}#{table_name_suffix}"
end
+ @quoted_table_name = nil
set_table_name(name)
name
end
@@ -1374,20 +1174,6 @@ module ActiveRecord #:nodoc:
store_full_sti_class ? name : name.demodulize
end
- # Merges conditions so that the result is a valid +condition+
- def merge_conditions(*conditions)
- segments = []
-
- conditions.each do |condition|
- unless condition.blank?
- sql = sanitize_sql(condition)
- segments << sql unless sql.blank?
- end
- end
-
- "(#{segments.join(') AND (')})" unless segments.empty?
- end
-
def unscoped
@unscoped ||= Relation.new(self, arel_table)
finder_needs_type_condition? ? @unscoped.where(type_condition) : @unscoped
@@ -2324,7 +2110,7 @@ module ActiveRecord #:nodoc:
def update(attribute_names = @attributes.keys)
attributes_with_values = arel_attributes_values(false, false, attribute_names)
return 0 if attributes_with_values.empty?
- self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).update(attributes_with_values)
+ self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.update(attributes_with_values)
end
# Creates a record with values matching those of the instance attributes
@@ -2548,10 +2334,6 @@ module ActiveRecord #:nodoc:
hash.inject([]) { |list, pair| list << "#{pair.first} = #{pair.last}" }.join(", ")
end
- def self.quoted_table_name
- self.connection.quote_table_name(self.table_name)
- end
-
def quote_columns(quoter, hash)
hash.inject({}) do |quoted, (name, value)|
quoted[quoter.quote_column_name(name)] = value
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index bf0683eb8f..9044ca418b 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -84,7 +84,7 @@ module ActiveRecord
relation.table[self.class.primary_key].eq(quoted_id).and(
relation.table[self.class.locking_column].eq(quote_value(previous_value))
)
- ).update(arel_attributes_values(false, false, attribute_names))
+ ).arel.update(arel_attributes_values(false, false, attribute_names))
unless affected_rows == 1
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index d606934dce..ff6c041ef4 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -165,7 +165,7 @@ module ActiveRecord
end
def ==(other)
- other.respond_to?(:to_a) ? to_a == other.to_a : false
+ other.respond_to?(:to_ary) ? to_a == other.to_a : false
end
private
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index decde50427..c9fff15199 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -8,7 +8,7 @@ module ActiveRecord
include FinderMethods, Calculations, SpawnMethods, QueryMethods
delegate :length, :collect, :map, :each, :all?, :include?, :to => :to_a
- delegate :insert, :update, :to => :arel
+ delegate :insert, :to => :arel
attr_reader :table, :klass
@@ -80,19 +80,177 @@ module ActiveRecord
if block_given?
to_a.many? { |*block_args| yield(*block_args) }
else
- arel.send(:taken).present? ? to_a.many? : size > 1
+ @limit_value.present? ? to_a.many? : size > 1
end
end
- def destroy_all
- to_a.each {|object| object.destroy}
- reset
+ # 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
+ # +before_destroy+/+after_destroy+ Observer methods). Returns the
+ # collection of objects that were destroyed; each will be frozen, to
+ # reflect that no changes should be made (since they can't be
+ # persisted).
+ #
+ # Note: Instantiation, callback execution, and deletion of each
+ # record can be time consuming when you're removing many records at
+ # once. It generates at least one SQL +DELETE+ query per record (or
+ # possibly more, to enforce your callbacks). If you want to delete many
+ # rows quickly, without concern for their associations or callbacks, use
+ # +delete_all+ instead.
+ #
+ # ==== Parameters
+ #
+ # * +conditions+ - A string, array, or hash that specifies which records
+ # to destroy. If omitted, all records are destroyed. See the
+ # Conditions section in the introduction to ActiveRecord::Base for
+ # more information.
+ #
+ # ==== Examples
+ #
+ # Person.destroy_all("last_login < '2004-04-04'")
+ # Person.destroy_all(:status => "inactive")
+ def destroy_all(conditions = nil)
+ if conditions
+ where(conditions).destroy_all
+ else
+ to_a.each {|object| object.destroy}
+ reset
+ end
+ end
+
+ # Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
+ # therefore all callbacks and filters are fired off before the object is deleted. This method is
+ # less efficient than ActiveRecord#delete but allows cleanup methods and other actions to be run.
+ #
+ # This essentially finds the object (or multiple objects) with the given id, creates a new object
+ # from the attributes, and then calls destroy on it.
+ #
+ # ==== Parameters
+ #
+ # * +id+ - Can be either an Integer or an Array of Integers.
+ #
+ # ==== Examples
+ #
+ # # Destroy a single object
+ # Todo.destroy(1)
+ #
+ # # Destroy multiple objects
+ # todos = [1,2,3]
+ # Todo.destroy(todos)
+ def destroy(id)
+ if id.is_a?(Array)
+ id.map { |one_id| destroy(one_id) }
+ else
+ find(id).destroy
+ end
end
- def delete_all
- arel.delete.tap { reset }
+ # Deletes the records matching +conditions+ without instantiating the records first, and hence not
+ # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that
+ # goes straight to the database, much more efficient than +destroy_all+. Be careful with relations
+ # though, in particular <tt>:dependent</tt> rules defined on associations are not honored. Returns
+ # the number of rows affected.
+ #
+ # ==== Parameters
+ #
+ # * +conditions+ - Conditions are specified the same way as with +find+ method.
+ #
+ # ==== Example
+ #
+ # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
+ # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
+ #
+ # Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent
+ # associations or call your <tt>before_*</tt> or +after_destroy+ callbacks, use the +destroy_all+ method instead.
+ def delete_all(conditions = nil)
+ conditions ? where(conditions).delete_all : arel.delete.tap { reset }
end
+ # Deletes the row with a primary key matching the +id+ argument, using a
+ # SQL +DELETE+ statement, and returns the number of rows deleted. Active
+ # Record objects are not instantiated, so the object's callbacks are not
+ # executed, including any <tt>:dependent</tt> association options or
+ # Observer methods.
+ #
+ # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
+ #
+ # Note: Although it is often much faster than the alternative,
+ # <tt>#destroy</tt>, skipping callbacks might bypass business logic in
+ # your application that ensures referential integrity or performs other
+ # essential jobs.
+ #
+ # ==== Examples
+ #
+ # # Delete a single row
+ # Todo.delete(1)
+ #
+ # # Delete multiple rows
+ # Todo.delete([2,3,4])
def delete(id_or_array)
where(@klass.primary_key => id_or_array).delete_all
end
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 999309d2bd..d6d3d66642 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -119,10 +119,40 @@ module ActiveRecord
args.any? ? apply_finder_options(args.first).to_a : to_a
end
+ # Returns true if a record exists in the table that matches the +id+ or
+ # conditions given, or false otherwise. The argument can take five forms:
+ #
+ # * Integer - Finds the record with this primary key.
+ # * String - Finds the record with a primary key corresponding to this
+ # string (such as <tt>'5'</tt>).
+ # * Array - Finds the record that matches these +find+-style conditions
+ # (such as <tt>['color = ?', 'red']</tt>).
+ # * Hash - Finds the record that matches these +find+-style conditions
+ # (such as <tt>{:color => 'red'}</tt>).
+ # * No args - Returns false if the table is empty, true otherwise.
+ #
+ # For more information about specifying conditions as a Hash or Array,
+ # see the Conditions section in the introduction to ActiveRecord::Base.
+ #
+ # Note: You can't pass in a condition as a string (like <tt>name =
+ # 'Jamie'</tt>), since it would be sanitized and then queried against
+ # the primary key column, like <tt>id = 'name = \'Jamie\''</tt>.
+ #
+ # ==== Examples
+ # Person.exists?(5)
+ # Person.exists?('5')
+ # Person.exists?(:name => "David")
+ # Person.exists?(['name LIKE ?', "%#{query}%"])
+ # Person.exists?
def exists?(id = nil)
- relation = select(primary_key).limit(1)
- relation = relation.where(primary_key.eq(id)) if id
- relation.first ? true : false
+ case id
+ when Array, Hash
+ where(id).exists?
+ else
+ relation = select(primary_key).limit(1)
+ relation = relation.where(primary_key.eq(id)) if id
+ relation.first ? true : false
+ end
end
protected
@@ -242,15 +272,15 @@ module ActiveRecord
result = where(primary_key.in(ids)).all
expected_size =
- if arel.taken && ids.size > arel.taken
- arel.taken
+ if @limit_value && ids.size > @limit_value
+ @limit_value
else
ids.size
end
# 11 ids with limit 3, offset 9 should give 2 results.
- if arel.skipped && (ids.size - arel.skipped < expected_size)
- expected_size = ids.size - arel.skipped
+ if @offset_value && (ids.size - @offset_value < expected_size)
+ expected_size = ids.size - @offset_value
end
if result.size == expected_size
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 163d698b5c..d0689cd93e 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -140,16 +140,18 @@ module ActiveRecord
selects = @select_values.uniq
+ quoted_table_name = @klass.quoted_table_name
+
if selects.present?
selects.each do |s|
@implicit_readonly = false
arel = arel.project(s) if s.present?
end
- elsif joins.present?
- arel = arel.project(@klass.quoted_table_name + '.*')
+ else
+ arel = arel.project(quoted_table_name + '.*')
end
- arel = arel.from(@from_value) if @from_value.present?
+ arel = @from_value.present? ? arel.from(@from_value) : arel.from(quoted_table_name)
case @lock_value
when TrueClass
@@ -167,8 +169,8 @@ module ActiveRecord
builder = PredicateBuilder.new(table.engine)
conditions = if [String, Array].include?(args.first.class)
- merged = @klass.send(:merge_conditions, args.size > 1 ? Array.wrap(args) : args.first)
- Arel::SqlLiteral.new(merged) if merged
+ sql = @klass.send(:sanitize_sql, args.size > 1 ? args : args.first)
+ Arel::SqlLiteral.new("(#{sql})") if sql.present?
elsif args.first.is_a?(Hash)
attributes = @klass.send(:expand_hash_conditions_for_aggregates, args.first)
builder.build_from_hash(attributes, table)
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 1577a9b116..cccf413e67 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -1,17 +1,7 @@
module ActiveRecord
module SpawnMethods
- def spawn(arel_table = self.table)
- relation = self.class.new(@klass, arel_table)
-
- (Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).each do |query_method|
- relation.send(:"#{query_method}_values=", send(:"#{query_method}_values"))
- end
-
- Relation::SINGLE_VALUE_METHODS.each do |query_method|
- relation.send(:"#{query_method}_value=", send(:"#{query_method}_value"))
- end
-
- relation
+ def spawn
+ clone.reset
end
def merge(r)