module ActiveRecord
# = Active Record Errors
#
# 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
# +config/database.yml+ misses adapter field).
class AdapterNotSpecified < ActiveRecordError
end
# Raised when Active Record cannot find database adapter specified in
# +config/database.yml+ or programmatically.
class AdapterNotFound < ActiveRecordError
end
# Raised when connection to the database could not been established (for
# example when +connection=+ 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
attr_reader :model, :primary_key, :id
def initialize(message = nil, model = nil, primary_key = nil, id = nil)
@primary_key = primary_key
@model = model
@id = id
super(message)
end
end
# Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
# saved because record is invalid.
class RecordNotSaved < ActiveRecordError
attr_reader :record
def initialize(message, record = nil)
@record = record
super(message)
end
end
# Raised by ActiveRecord::Base.destroy! when a call to destroy would return false.
#
# begin
# complex_operation_that_internally_calls_destroy!
# rescue ActiveRecord::RecordNotDestroyed => invalid
# puts invalid.record.errors
# end
#
class RecordNotDestroyed < ActiveRecordError
attr_reader :record
def initialize(message, record = nil)
@record = record
super(message)
end
end
# Superclass for all database execution errors.
#
# Wraps the underlying database error as +original_exception+.
class StatementInvalid < ActiveRecordError
attr_reader :original_exception
def initialize(message, original_exception = nil)
super(message)
@original_exception = original_exception
end
end
# Defunct wrapper class kept for compatibility.
# +StatementInvalid+ wraps the original exception now.
class WrappedDatabaseException < StatementInvalid
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 +:condition+ key
# (for example, when using +find+ method) does not match number of expected
# values supplied.
#
# For example, when there are two placeholders with only one value supplied:
#
# Location.where("lat = ? AND lng = ?", 53.7362)
class PreparedStatementInvalid < ActiveRecordError
end
# Raised when a given database does not exist.
class NoDatabaseError < StatementInvalid
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
# documentation.
class StaleObjectError < ActiveRecordError
attr_reader :record, :attempted_action
def initialize(record, attempted_action)
super("Attempted to #{attempted_action} a stale object: #{record.class.name}")
@record = record
@attempted_action = attempted_action
end
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.
UnknownAttributeError = ActiveModel::UnknownAttributeError
# Raised when an error occurred while doing a mass assignment to an attribute through the
# +attributes=+ 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)
super(message)
@exception = exception
@attribute = attribute
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
# Raised when a primary key is needed, but not specified in the schema or model.
class UnknownPrimaryKey < ActiveRecordError
attr_reader :model
def initialize(model, description = nil)
message = "Unknown primary key for table #{model.table_name} in model #{model}."
message += "\n#{description}" if description
super(message)
@model = model
end
end
# Raised when a relation cannot be mutated because it's already loaded.
#
# class Task < ActiveRecord::Base
# end
#
# relation = Task.all
# relation.loaded? # => true
#
# # Methods which try to mutate a loaded relation fail.
# relation.where!(title: 'TODO') # => ActiveRecord::ImmutableRelation
# relation.limit!(5) # => ActiveRecord::ImmutableRelation
class ImmutableRelation < ActiveRecordError
end
# TransactionIsolationError will be raised under the following conditions:
#
# * The adapter does not support setting the isolation level
# * You are joining an existing open transaction
# * You are creating a nested (savepoint) transaction
#
# The mysql, mysql2 and postgresql adapters support setting the transaction isolation level.
class TransactionIsolationError < ActiveRecordError
end
end