aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorMikel Lindsaar <raasdnil@gmail.com>2010-03-11 22:05:15 +1100
committerMikel Lindsaar <raasdnil@gmail.com>2010-03-11 22:05:15 +1100
commitf5774e3e3f70a3acfa559b9ff889e9417fb71d4b (patch)
treee738112994d40d6c3792065da80bddfa7439467b /activerecord/lib
parentcefe723e285f20d1f2a33f67da03348568f7e0b0 (diff)
parent073852dff0b48296a9a184f94e722183334f3c4c (diff)
downloadrails-f5774e3e3f70a3acfa559b9ff889e9417fb71d4b.tar.gz
rails-f5774e3e3f70a3acfa559b9ff889e9417fb71d4b.tar.bz2
rails-f5774e3e3f70a3acfa559b9ff889e9417fb71d4b.zip
Merge branch 'master' of git://github.com/rails/rails
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record.rb13
-rwxr-xr-xactiverecord/lib/active_record/associations.rb56
-rwxr-xr-xactiverecord/lib/active_record/base.rb179
-rw-r--r--activerecord/lib/active_record/errors.rb165
-rw-r--r--activerecord/lib/active_record/named_scope.rb2
-rw-r--r--activerecord/lib/active_record/railtie.rb42
-rw-r--r--activerecord/lib/active_record/relation.rb4
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb2
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb26
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb8
10 files changed, 250 insertions, 247 deletions
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index b79da4565d..5942640c85 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -30,7 +30,6 @@ $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include
require 'active_support'
require 'active_model'
-require 'arel'
module ActiveRecord
extend ActiveSupport::Autoload
@@ -38,8 +37,8 @@ module ActiveRecord
eager_autoload do
autoload :VERSION
- autoload :ActiveRecordError, 'active_record/base'
- autoload :ConnectionNotEstablished, 'active_record/base'
+ autoload :ActiveRecordError, 'active_record/errors'
+ autoload :ConnectionNotEstablished, 'active_record/errors'
autoload :Aggregations
autoload :AssociationPreload
@@ -106,12 +105,16 @@ module ActiveRecord
eager_autoload do
autoload :AbstractAdapter
+ autoload :ConnectionManagement, "active_record/connection_adapters/abstract/connection_pool"
end
end
autoload :TestCase
autoload :TestFixtures, 'active_record/fixtures'
+
+ base_hook do
+ Arel::Table.engine = Arel::Sql::Engine.new(self)
+ end
end
-Arel::Table.engine = Arel::Sql::Engine.new(ActiveRecord::Base)
-I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
+I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml' \ No newline at end of file
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 57785b4c93..b69577f8dd 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1537,58 +1537,42 @@ module ActiveRecord
# has_one associated objects, according to the defined :dependent rule.
def configure_dependency_for_has_one(reflection)
if reflection.options.include?(:dependent)
- case reflection.options[:dependent]
- when :destroy
- method_name = "has_one_dependent_destroy_for_#{reflection.name}".to_sym
- define_method(method_name) do
- association = send(reflection.name)
- association.destroy unless association.nil?
- end
- before_destroy method_name
- when :delete
- method_name = "has_one_dependent_delete_for_#{reflection.name}".to_sym
+ name = reflection.options[:dependent]
+ method_name = :"has_one_dependent_#{name}_for_#{reflection.name}"
+
+ case name
+ when :destroy, :delete
define_method(method_name) do
- # Retrieve the associated object and delete it. The retrieval
- # is necessary because there may be multiple associated objects
- # with foreign keys pointing to this object, and we only want
- # to delete the correct one, not all of them.
association = send(reflection.name)
- association.delete unless association.nil?
+ association.send(name) if association
end
- before_destroy method_name
when :nullify
- method_name = "has_one_dependent_nullify_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send(reflection.name)
- association.update_attribute(reflection.primary_key_name, nil) unless association.nil?
+ association.update_attribute(reflection.primary_key_name, nil) if association
end
- before_destroy method_name
else
raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})"
end
+
+ before_destroy method_name
end
end
def configure_dependency_for_belongs_to(reflection)
if reflection.options.include?(:dependent)
- case reflection.options[:dependent]
- when :destroy
- method_name = "belongs_to_dependent_destroy_for_#{reflection.name}".to_sym
- define_method(method_name) do
- association = send(reflection.name)
- association.destroy unless association.nil?
- end
- after_destroy method_name
- when :delete
- method_name = "belongs_to_dependent_delete_for_#{reflection.name}".to_sym
- define_method(method_name) do
- association = send(reflection.name)
- association.delete unless association.nil?
- end
- after_destroy method_name
- else
- raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
+ name = reflection.options[:dependent]
+
+ unless [:destroy, :delete].include?(name)
+ raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
+ end
+
+ method_name = :"belongs_to_dependent_#{name}_for_#{reflection.name}"
+ define_method(method_name) do
+ association = send(reflection.name)
+ association.send(name) if association
end
+ after_destroy method_name
end
end
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index cd67490573..52587ef251 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -13,172 +13,10 @@ require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/behavior'
require 'active_support/core_ext/object/singleton_class'
require 'active_support/core_ext/module/delegation'
+require 'arel'
+require 'active_record/errors'
module ActiveRecord #:nodoc:
- # Generic Active Record exception class.
- class ActiveRecordError < StandardError
- end
-
- # Raised when the single-table inheritance mechanism fails to locate the subclass
- # (for example due to improper usage of column that +inheritance_column+ points to).
- class SubclassNotFound < ActiveRecordError #:nodoc:
- end
-
- # Raised when an object assigned to an association has an incorrect type.
- #
- # class Ticket < ActiveRecord::Base
- # has_many :patches
- # end
- #
- # class Patch < ActiveRecord::Base
- # belongs_to :ticket
- # end
- #
- # # Comments are not patches, this assignment raises AssociationTypeMismatch.
- # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
- class AssociationTypeMismatch < ActiveRecordError
- end
-
- # Raised when unserialized object's type mismatches one specified for serializable field.
- class SerializationTypeMismatch < ActiveRecordError
- end
-
- # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
- class AdapterNotSpecified < ActiveRecordError
- end
-
- # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
- class AdapterNotFound < ActiveRecordError
- end
-
- # Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
- class ConnectionNotEstablished < ActiveRecordError
- end
-
- # Raised when Active Record cannot find record by given id or set of ids.
- class RecordNotFound < ActiveRecordError
- end
-
- # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
- # saved because record is invalid.
- class RecordNotSaved < ActiveRecordError
- end
-
- # Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
- class StatementInvalid < ActiveRecordError
- end
-
- # Raised when SQL statement is invalid and the application gets a blank result.
- class ThrowResult < ActiveRecordError
- end
-
- # Parent class for all specific exceptions which wrap database driver exceptions
- # provides access to the original exception also.
- class WrappedDatabaseException < StatementInvalid
- attr_reader :original_exception
-
- def initialize(message, original_exception)
- super(message)
- @original_exception = original_exception
- end
- end
-
- # Raised when a record cannot be inserted because it would violate a uniqueness constraint.
- class RecordNotUnique < WrappedDatabaseException
- end
-
- # Raised when a record cannot be inserted or updated because it references a non-existent record.
- class InvalidForeignKey < WrappedDatabaseException
- end
-
- # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
- # does not match number of expected variables.
- #
- # For example, in
- #
- # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
- #
- # two placeholders are given but only one variable to fill them.
- class PreparedStatementInvalid < ActiveRecordError
- end
-
- # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
- # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
- # the page before the other.
- #
- # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
- class StaleObjectError < ActiveRecordError
- end
-
- # Raised when association is being configured improperly or
- # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
- class ConfigurationError < ActiveRecordError
- end
-
- # Raised on attempt to update record that is instantiated as read only.
- class ReadOnlyRecord < ActiveRecordError
- end
-
- # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
- # to distinguish a deliberate rollback from other exceptional situations.
- # Normally, raising an exception will cause the +transaction+ method to rollback
- # the database transaction *and* pass on the exception. But if you raise an
- # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
- # without passing on the exception.
- #
- # For example, you could do this in your controller to rollback a transaction:
- #
- # class BooksController < ActionController::Base
- # def create
- # Book.transaction do
- # book = Book.new(params[:book])
- # book.save!
- # if today_is_friday?
- # # The system must fail on Friday so that our support department
- # # won't be out of job. We silently rollback this transaction
- # # without telling the user.
- # raise ActiveRecord::Rollback, "Call tech support!"
- # end
- # end
- # # ActiveRecord::Rollback is the only exception that won't be passed on
- # # by ActiveRecord::Base.transaction, so this line will still be reached
- # # even on Friday.
- # redirect_to root_url
- # end
- # end
- class Rollback < ActiveRecordError
- end
-
- # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
- class DangerousAttributeError < ActiveRecordError
- end
-
- # Raised when unknown attributes are supplied via mass assignment.
- class UnknownAttributeError < NoMethodError
- end
-
- # Raised when an error occurred while doing a mass assignment to an attribute through the
- # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
- # offending attribute.
- class AttributeAssignmentError < ActiveRecordError
- attr_reader :exception, :attribute
- def initialize(message, exception, attribute)
- @exception = exception
- @attribute = attribute
- @message = message
- end
- end
-
- # Raised when there are multiple errors while doing a mass assignment through the +attributes+
- # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
- # objects, each corresponding to the error while assigning to an attribute.
- class MultiparameterAssignmentErrors < ActiveRecordError
- attr_reader :errors
- def initialize(errors)
- @errors = errors
- end
- end
-
# Active Record objects don't specify their attributes directly, but rather infer them from the table definition with
# which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change
# is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain
@@ -551,7 +389,7 @@ module ActiveRecord #:nodoc:
class << self # Class methods
def colorize_logging(*args)
ActiveSupport::Deprecation.warn "ActiveRecord::Base.colorize_logging and " <<
- "config.active_record.colorize_logging are deprecated. Please use " <<
+ "config.active_record.colorize_logging are deprecated. Please use " <<
"Rails::LogSubscriber.colorize_logging or config.colorize_logging instead", caller
end
alias :colorize_logging= :colorize_logging
@@ -2001,10 +1839,9 @@ module ActiveRecord #:nodoc:
# Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
def attributes
- self.attribute_names.inject({}) do |attrs, name|
- attrs[name] = read_attribute(name)
- attrs
- end
+ attrs = {}
+ attribute_names.each { |name| attrs[name] = read_attribute(name) }
+ attrs
end
# Returns an <tt>#inspect</tt>-like string for the value of the
@@ -2348,7 +2185,7 @@ module ActiveRecord #:nodoc:
# Returns a comma-separated pair list, like "key1 = val1, key2 = val2".
def comma_pair_list(hash)
- hash.inject([]) { |list, pair| list << "#{pair.first} = #{pair.last}" }.join(", ")
+ hash.map { |k,v| "#{k} = #{v}" }.join(", ")
end
def quote_columns(quoter, hash)
@@ -2402,8 +2239,10 @@ module ActiveRecord #:nodoc:
include Aggregations, Transactions, Reflection, Serialization
+ NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner)
end
end
# TODO: Remove this and make it work with LAZY flag
require 'active_record/connection_adapters/abstract_adapter'
+ActiveRecord.run_base_hooks(ActiveRecord::Base) \ No newline at end of file
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
new file mode 100644
index 0000000000..cf5ddca2ba
--- /dev/null
+++ b/activerecord/lib/active_record/errors.rb
@@ -0,0 +1,165 @@
+module ActiveRecord
+ # Generic Active Record exception class.
+ class ActiveRecordError < StandardError
+ end
+
+ # Raised when the single-table inheritance mechanism fails to locate the subclass
+ # (for example due to improper usage of column that +inheritance_column+ points to).
+ class SubclassNotFound < ActiveRecordError #:nodoc:
+ end
+
+ # Raised when an object assigned to an association has an incorrect type.
+ #
+ # class Ticket < ActiveRecord::Base
+ # has_many :patches
+ # end
+ #
+ # class Patch < ActiveRecord::Base
+ # belongs_to :ticket
+ # end
+ #
+ # # Comments are not patches, this assignment raises AssociationTypeMismatch.
+ # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
+ class AssociationTypeMismatch < ActiveRecordError
+ end
+
+ # Raised when unserialized object's type mismatches one specified for serializable field.
+ class SerializationTypeMismatch < ActiveRecordError
+ end
+
+ # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
+ class AdapterNotSpecified < ActiveRecordError
+ end
+
+ # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
+ class AdapterNotFound < ActiveRecordError
+ end
+
+ # Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
+ class ConnectionNotEstablished < ActiveRecordError
+ end
+
+ # Raised when Active Record cannot find record by given id or set of ids.
+ class RecordNotFound < ActiveRecordError
+ end
+
+ # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
+ # saved because record is invalid.
+ class RecordNotSaved < ActiveRecordError
+ end
+
+ # Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
+ class StatementInvalid < ActiveRecordError
+ end
+
+ # Raised when SQL statement is invalid and the application gets a blank result.
+ class ThrowResult < ActiveRecordError
+ end
+
+ # Parent class for all specific exceptions which wrap database driver exceptions
+ # provides access to the original exception also.
+ class WrappedDatabaseException < StatementInvalid
+ attr_reader :original_exception
+
+ def initialize(message, original_exception)
+ super(message)
+ @original_exception = original_exception
+ end
+ end
+
+ # Raised when a record cannot be inserted because it would violate a uniqueness constraint.
+ class RecordNotUnique < WrappedDatabaseException
+ end
+
+ # Raised when a record cannot be inserted or updated because it references a non-existent record.
+ class InvalidForeignKey < WrappedDatabaseException
+ end
+
+ # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
+ # does not match number of expected variables.
+ #
+ # For example, in
+ #
+ # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
+ #
+ # two placeholders are given but only one variable to fill them.
+ class PreparedStatementInvalid < ActiveRecordError
+ end
+
+ # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
+ # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
+ # the page before the other.
+ #
+ # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
+ class StaleObjectError < ActiveRecordError
+ end
+
+ # Raised when association is being configured improperly or
+ # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
+ class ConfigurationError < ActiveRecordError
+ end
+
+ # Raised on attempt to update record that is instantiated as read only.
+ class ReadOnlyRecord < ActiveRecordError
+ end
+
+ # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
+ # to distinguish a deliberate rollback from other exceptional situations.
+ # Normally, raising an exception will cause the +transaction+ method to rollback
+ # the database transaction *and* pass on the exception. But if you raise an
+ # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
+ # without passing on the exception.
+ #
+ # For example, you could do this in your controller to rollback a transaction:
+ #
+ # class BooksController < ActionController::Base
+ # def create
+ # Book.transaction do
+ # book = Book.new(params[:book])
+ # book.save!
+ # if today_is_friday?
+ # # The system must fail on Friday so that our support department
+ # # won't be out of job. We silently rollback this transaction
+ # # without telling the user.
+ # raise ActiveRecord::Rollback, "Call tech support!"
+ # end
+ # end
+ # # ActiveRecord::Rollback is the only exception that won't be passed on
+ # # by ActiveRecord::Base.transaction, so this line will still be reached
+ # # even on Friday.
+ # redirect_to root_url
+ # end
+ # end
+ class Rollback < ActiveRecordError
+ end
+
+ # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
+ class DangerousAttributeError < ActiveRecordError
+ end
+
+ # Raised when unknown attributes are supplied via mass assignment.
+ class UnknownAttributeError < NoMethodError
+ end
+
+ # Raised when an error occurred while doing a mass assignment to an attribute through the
+ # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
+ # offending attribute.
+ class AttributeAssignmentError < ActiveRecordError
+ attr_reader :exception, :attribute
+ def initialize(message, exception, attribute)
+ @exception = exception
+ @attribute = attribute
+ @message = message
+ end
+ end
+
+ # Raised when there are multiple errors while doing a mass assignment through the +attributes+
+ # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
+ # objects, each corresponding to the error while assigning to an attribute.
+ class MultiparameterAssignmentErrors < ActiveRecordError
+ attr_reader :errors
+ def initialize(errors)
+ @errors = errors
+ end
+ end
+end \ No newline at end of file
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index f1f56850ae..394e1587e1 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -26,7 +26,7 @@ module ActiveRecord
if options.present?
Scope.init(self, options, &block)
else
- current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.spawn
+ current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
end
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index b38bd9a644..60addd46c6 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -24,31 +24,39 @@ module ActiveRecord
log_subscriber ActiveRecord::Railties::LogSubscriber.new
initializer "active_record.initialize_timezone" do
- ActiveRecord::Base.time_zone_aware_attributes = true
- ActiveRecord::Base.default_timezone = :utc
+ ActiveRecord.base_hook do
+ self.time_zone_aware_attributes = true
+ self.default_timezone = :utc
+ end
end
initializer "active_record.logger" do
- ActiveRecord::Base.logger ||= ::Rails.logger
+ ActiveRecord.base_hook { self.logger ||= ::Rails.logger }
end
initializer "active_record.set_configs" do |app|
- app.config.active_record.each do |k,v|
- ActiveRecord::Base.send "#{k}=", v
+ ActiveRecord.base_hook do
+ app.config.active_record.each do |k,v|
+ send "#{k}=", v
+ end
end
end
# This sets the database configuration from Configuration#database_configuration
# and then establishes the connection.
initializer "active_record.initialize_database" do |app|
- ActiveRecord::Base.configurations = app.config.database_configuration
- ActiveRecord::Base.establish_connection
+ ActiveRecord.base_hook do
+ self.configurations = app.config.database_configuration
+ establish_connection
+ end
end
# Expose database runtime to controller for logging.
initializer "active_record.log_runtime" do |app|
require "active_record/railties/controller_runtime"
- ActionController::Base.send :include, ActiveRecord::Railties::ControllerRuntime
+ ActionController.base_hook do
+ include ActiveRecord::Railties::ControllerRuntime
+ end
end
# Setup database middleware after initializers have run
@@ -64,18 +72,22 @@ module ActiveRecord
end
initializer "active_record.load_observers" do
- ActiveRecord::Base.instantiate_observers
+ ActiveRecord.base_hook { instantiate_observers }
- ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do
- ActiveRecord::Base.instantiate_observers
+ ActiveRecord.base_hook do
+ ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do
+ ActiveRecord::Base.instantiate_observers
+ end
end
end
initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app|
- unless app.config.cache_classes
- ActionDispatch::Callbacks.after do
- ActiveRecord::Base.reset_subclasses
- ActiveRecord::Base.clear_reloadable_connections!
+ ActiveRecord.base_hook do
+ unless app.config.cache_classes
+ ActionDispatch::Callbacks.after do
+ ActiveRecord::Base.reset_subclasses
+ ActiveRecord::Base.clear_reloadable_connections!
+ end
end
end
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 7bc3d3bf33..aca4629dd8 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -21,6 +21,10 @@ module ActiveRecord
with_create_scope { @klass.new(*args, &block) }
end
+ def initialize_copy(other)
+ reset
+ end
+
alias build new
def create(*args, &block)
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 65e5c0495c..7e83eccbb5 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -20,7 +20,7 @@ module ActiveRecord
table = Arel::Table.new(table_name, :engine => @engine)
end
- attribute = table[column] || Arel::Attribute.new(table, column.to_sym)
+ attribute = table[column]
case value
when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 25ffa7860e..e00d9cdf27 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -8,7 +8,7 @@ module ActiveRecord
class_eval <<-CEVAL
def #{query_method}(*args)
- new_relation = spawn
+ new_relation = clone
value = Array.wrap(args.flatten).reject {|x| x.blank? }
new_relation.#{query_method}_values += value if value.present?
new_relation
@@ -19,7 +19,7 @@ module ActiveRecord
[:where, :having].each do |query_method|
class_eval <<-CEVAL
def #{query_method}(*args)
- new_relation = spawn
+ new_relation = clone
value = build_where(*args)
new_relation.#{query_method}_values += [*value] if value.present?
new_relation
@@ -32,7 +32,7 @@ module ActiveRecord
class_eval <<-CEVAL
def #{query_method}(value = true)
- new_relation = spawn
+ new_relation = clone
new_relation.#{query_method}_value = value
new_relation
end
@@ -41,12 +41,12 @@ module ActiveRecord
end
def lock(locks = true)
- relation = spawn
+ relation = clone
case locks
when String, TrueClass, NilClass
- spawn.tap {|new_relation| new_relation.lock_value = locks || true }
+ clone.tap {|new_relation| new_relation.lock_value = locks || true }
else
- spawn.tap {|new_relation| new_relation.lock_value = false }
+ clone.tap {|new_relation| new_relation.lock_value = false }
end
end
@@ -184,16 +184,16 @@ module ActiveRecord
builder = PredicateBuilder.new(table.engine)
- conditions = if [String, Array].include?(args.first.class)
- @klass.send(:sanitize_sql, args.size > 1 ? args : args.first)
- elsif args.first.is_a?(Hash)
- attributes = @klass.send(:expand_hash_conditions_for_aggregates, args.first)
+ opts = args.first
+ case opts
+ when String, Array
+ @klass.send(:sanitize_sql, args.size > 1 ? args : opts)
+ when Hash
+ attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
builder.build_from_hash(attributes, table)
else
- args.first
+ opts
end
-
- conditions
end
private
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index cccf413e67..a18380f01c 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -1,11 +1,7 @@
module ActiveRecord
module SpawnMethods
- def spawn
- clone.reset
- end
-
def merge(r)
- merged_relation = spawn
+ merged_relation = clone
return merged_relation unless r
merged_relation = merged_relation.eager_load(r.eager_load_values).preload(r.preload_values).includes(r.includes_values)
@@ -83,7 +79,7 @@ module ActiveRecord
:order, :select, :readonly, :group, :having, :from, :lock ]
def apply_finder_options(options)
- relation = spawn
+ relation = clone
return relation unless options
options.assert_valid_keys(VALID_FIND_OPTIONS)