aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/base.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/base.rb')
-rwxr-xr-xactiverecord/lib/active_record/base.rb200
1 files changed, 22 insertions, 178 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 318bfbe826..52587ef251 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -11,174 +11,12 @@ require 'active_support/core_ext/hash/deep_merge'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/behavior'
-require 'active_support/core_ext/object/metaclass'
+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
-
- # <tt>ActiveRecord::Transactions::ClassMethods.transaction</tt> 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
- # <tt>ActiveRecord::Rollback</tt> 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,8 +389,8 @@ 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 " <<
- "Rails::Subscriber.colorize_logging or config.colorize_logging instead", caller
+ "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
@@ -1669,12 +1507,12 @@ module ActiveRecord #:nodoc:
@attributes_cache = {}
@new_record = true
ensure_proper_type
- self.attributes = attributes unless attributes.nil?
if scope = self.class.send(:current_scoped_methods)
create_with = scope.scope_for_create
create_with.each { |att,value| self.send("#{att}=", value) } if create_with
end
+ self.attributes = attributes unless attributes.nil?
result = yield self if block_given?
_run_initialize_callbacks
@@ -1767,6 +1605,11 @@ module ActiveRecord #:nodoc:
@destroyed || false
end
+ # Returns if the record is persisted, i.e. it's not a new record and it was not destroyed.
+ def persisted?
+ !(new_record? || destroyed?)
+ end
+
# :call-seq:
# save(options)
#
@@ -1816,7 +1659,7 @@ module ActiveRecord #:nodoc:
# callbacks, Observer methods, or any <tt>:dependent</tt> association
# options, use <tt>#destroy</tt>.
def delete
- self.class.delete(id) unless new_record?
+ self.class.delete(id) if persisted?
@destroyed = true
freeze
end
@@ -1824,7 +1667,7 @@ module ActiveRecord #:nodoc:
# Deletes the record in the database and freezes this instance to reflect that no changes should
# be made (since they can't be persisted).
def destroy
- unless new_record?
+ if persisted?
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all
end
@@ -1844,6 +1687,7 @@ module ActiveRecord #:nodoc:
became.instance_variable_set("@attributes", @attributes)
became.instance_variable_set("@attributes_cache", @attributes_cache)
became.instance_variable_set("@new_record", new_record?)
+ became.instance_variable_set("@destroyed", destroyed?)
became
end
@@ -1926,7 +1770,7 @@ module ActiveRecord #:nodoc:
def reload(options = nil)
clear_aggregation_cache
clear_association_cache
- @attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
+ @attributes.update(self.class.send(:with_exclusive_scope) { self.class.find(self.id, options) }.instance_variable_get('@attributes'))
@attributes_cache = {}
self
end
@@ -1995,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
@@ -2042,8 +1885,7 @@ module ActiveRecord #:nodoc:
def ==(comparison_object)
comparison_object.equal?(self) ||
(comparison_object.instance_of?(self.class) &&
- comparison_object.id == id &&
- !comparison_object.new_record?)
+ comparison_object.id == id && !comparison_object.new_record?)
end
# Delegates to ==
@@ -2343,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)
@@ -2397,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