From 4ff626cac901b41f86646dab1939d2a95b2d26bd Mon Sep 17 00:00:00 2001 From: Pavel Pravosud Date: Sat, 5 Sep 2015 17:48:15 -0700 Subject: Make ActiveRecordException descendants args optional This change allows to instantiate all ActiveRecordError descendant execption classes without arguments, which might be useful in testing and is far less surprising than mandatory arguments. --- activerecord/lib/active_record/associations.rb | 134 ++++++++++++++++++------- activerecord/lib/active_record/errors.rb | 38 ++++--- activerecord/lib/active_record/migration.rb | 42 +++++--- activerecord/lib/active_record/validations.rb | 14 ++- 4 files changed, 162 insertions(+), 66 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 19ef37e228..65eb6fba27 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -5,65 +5,105 @@ require 'active_record/errors' module ActiveRecord class AssociationNotFoundError < ConfigurationError #:nodoc: - def initialize(record, association_name) - super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?") + def initialize(record = nil, association_name = nil) + if record && association_name + super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?") + else + super("Association was not found.") + end end end class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc: - def initialize(reflection, associated_class = nil) - super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})") + def initialize(reflection = nil, associated_class = nil) + if reflection + super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})") + else + super("Could not find the inverse association.") + end end end class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc: - def initialize(owner_class_name, reflection) - super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}") + def initialize(owner_class_name = nil, reflection = nil) + if owner_class_name && reflection + super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}") + else + super("Could not find the association.") + end end end class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError #:nodoc: - def initialize(owner_class_name, reflection, source_reflection) - super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.") + def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil) + if owner_class_name && reflection && source_reflection + super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.") + else + super("Cannot have a has_many :through association.") + end end end class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError #:nodoc: - def initialize(owner_class_name, reflection) - super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.") + def initialize(owner_class_name = nil, reflection = nil) + if owner_class_name && reflection + super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.") + else + super("Cannot have a has_many :through association.") + end end end class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc: - def initialize(owner_class_name, reflection, source_reflection) - super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.") + def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil) + if owner_class_name && reflection && source_reflection + super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.") + else + super("Cannot have a has_many :through association.") + end end end class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc: - def initialize(owner_class_name, reflection, through_reflection) - super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.") + def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil) + if owner_class_name && reflection && through_reflection + super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.") + else + super("Cannot have a has_one :through association.") + end end end class HasOneAssociationPolymorphicThroughError < ActiveRecordError #:nodoc: - def initialize(owner_class_name, reflection) - super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.") + def initialize(owner_class_name = nil, reflection = nil) + if owner_class_name && reflection + super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.") + else + super("Cannot have a has_one :through association.") + end end end class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc: - def initialize(reflection) - through_reflection = reflection.through_reflection - source_reflection_names = reflection.source_reflection_names - source_associations = reflection.through_reflection.klass._reflections.keys - super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => '. Is it one of #{source_associations.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)}?") + def initialize(reflection = nil) + if reflection + through_reflection = reflection.through_reflection + source_reflection_names = reflection.source_reflection_names + source_associations = reflection.through_reflection.klass._reflections.keys + super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => '. Is it one of #{source_associations.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)}?") + else + super("Could not find the source association(s).") + end end end class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc: - def initialize(owner, reflection) - super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.") + def initialize(owner = nil, reflection = nil) + if owner && reflection + super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.") + else + super("Cannot modify association.") + end end end @@ -74,20 +114,32 @@ module ActiveRecord end class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc: - def initialize(owner, reflection) - super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.") + def initialize(owner = nil, reflection = nil) + if owner && reflection + super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.") + else + super("Cannot associate new records.") + end end end class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc: - def initialize(owner, reflection) - super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.") + def initialize(owner = nil, reflection = nil) + if owner && reflection + super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.") + else + super("Cannot dissociate new records.") + end end end class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc: - def initialize(owner, reflection) - super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.") + def initialize(owner = nil, reflection = nil) + if owner && reflection + super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.") + else + super("Through nested associations are read-only.") + end end end @@ -98,14 +150,22 @@ module ActiveRecord end class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: - def initialize(reflection) - super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}") + def initialize(reflection = nil) + if reflection + super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}") + else + super("Eager load polymorphic error.") + end end end class ReadOnlyAssociation < ActiveRecordError #:nodoc: - def initialize(reflection) - super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.") + def initialize(reflection = nil) + if reflection + super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.") + else + super("Read-only reflection error.") + end end end @@ -113,8 +173,12 @@ module ActiveRecord # (has_many, has_one) when there is at least 1 child associated instance. # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project class DeleteRestrictionError < ActiveRecordError #:nodoc: - def initialize(name) - super("Cannot delete record because of dependent #{name}") + def initialize(name = nil) + if name + super("Cannot delete record because of dependent #{name}") + else + super("Delete restriction error.") + end end end diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index 718f04871d..6721fe144f 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -63,7 +63,7 @@ module ActiveRecord class RecordNotSaved < ActiveRecordError attr_reader :record - def initialize(message, record = nil) + def initialize(message = nil, record = nil) @record = record super(message) end @@ -80,7 +80,7 @@ module ActiveRecord class RecordNotDestroyed < ActiveRecordError attr_reader :record - def initialize(message, record = nil) + def initialize(message = nil, record = nil) @record = record super(message) end @@ -92,9 +92,9 @@ module ActiveRecord class StatementInvalid < ActiveRecordError attr_reader :original_exception - def initialize(message, original_exception = nil) - super(message) + def initialize(message = nil, original_exception = nil) @original_exception = original_exception + super(message) end end @@ -134,10 +134,14 @@ module ActiveRecord 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 + def initialize(record = nil, attempted_action = nil) + if record && attempted_action + @record = record + @attempted_action = attempted_action + super("Attempted to #{attempted_action} a stale object: #{record.class.name}.") + else + super("Stale object error.") + end end end @@ -196,7 +200,7 @@ module ActiveRecord class AttributeAssignmentError < ActiveRecordError attr_reader :exception, :attribute - def initialize(message, exception, attribute) + def initialize(message = nil, exception = nil, attribute = nil) super(message) @exception = exception @attribute = attribute @@ -209,7 +213,7 @@ module ActiveRecord class MultiparameterAssignmentErrors < ActiveRecordError attr_reader :errors - def initialize(errors) + def initialize(errors = nil) @errors = errors end end @@ -218,11 +222,15 @@ module ActiveRecord 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 + def initialize(model = nil, description = nil) + if model + message = "Unknown primary key for table #{model.table_name} in model #{model}." + message += "\n#{description}" if description + @model = model + super(message) + else + super("Unknown primary key.") + end end end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 112d52024f..3b90ab1e31 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -84,35 +84,53 @@ module ActiveRecord end class DuplicateMigrationVersionError < MigrationError#:nodoc: - def initialize(version) - super("Multiple migrations have the version number #{version}") + def initialize(version = nil) + if version + super("Multiple migrations have the version number #{version}.") + else + super("Duplicate migration version error.") + end end end class DuplicateMigrationNameError < MigrationError#:nodoc: - def initialize(name) - super("Multiple migrations have the name #{name}") + def initialize(name = nil) + if name + super("Multiple migrations have the name #{name}.") + else + super("Duplicate migration name.") + end end end class UnknownMigrationVersionError < MigrationError #:nodoc: - def initialize(version) - super("No migration with version number #{version}") + def initialize(version = nil) + if version + super("No migration with version number #{version}.") + else + super("Unknown migration version.") + end end end class IllegalMigrationNameError < MigrationError#:nodoc: - def initialize(name) - super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed)") + def initialize(name = nil) + if name + super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).") + else + super("Illegal name for migration.") + end end end class PendingMigrationError < MigrationError#:nodoc: - def initialize - if defined?(Rails.env) - super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}") + def initialize(message = nil) + if !message && defined?(Rails.env) + super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}.") + elsif !message + super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate.") else - super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate") + super end end end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 34d96b19fe..74daece4e8 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -12,10 +12,16 @@ module ActiveRecord class RecordInvalid < ActiveRecordError attr_reader :record - def initialize(record) - @record = record - errors = @record.errors.full_messages.join(", ") - super(I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", :errors => errors, :default => :"errors.messages.record_invalid")) + def initialize(record = nil) + if record + @record = record + errors = @record.errors.full_messages.join(", ") + message = I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", errors: errors, default: :"errors.messages.record_invalid") + else + message = "Record invalid" + end + + super(message) end end -- cgit v1.2.3