diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 22f805fea4089..fb64156b78ad2 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,19 @@ +* ActiveRecord::RecordNotFound modified to store model name, primary_key and + id of the caller model. It allows the catcher of this exception to make + a better decision to what to do with it. For example consider this simple + example: + + class SomeAbstractController < ActionController::Base + rescue_from ActiveRecord::RecordNotFound, with: :redirect_to_404 + + private def redirect_to_404(e) + return redirect_to(posts_url) if e.model == 'Post' + raise + end + end + + *Sameer Rahmani* + * Deprecate the keys for association `restrict_dependent_destroy` errors in favor of new key names. diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index b82488a59cc4f..ffce2173ece6f 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -162,11 +162,13 @@ def find(*ids) # :nodoc: } record = statement.execute([id], self, connection).first unless record - raise RecordNotFound, "Couldn't find #{name} with '#{primary_key}'=#{id}" + raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", + name, primary_key, id) end record rescue RangeError - raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'" + raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'", + name, primary_key) end def find_by(*args) # :nodoc: @@ -199,7 +201,7 @@ def find_by(*args) # :nodoc: end def find_by!(*args) # :nodoc: - find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}") + find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}", name) end def initialize_generated_modules # :nodoc: diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index 0f1759abaafdd..d589620f8a7f9 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -47,6 +47,15 @@ class ConnectionNotEstablished < ActiveRecordError # 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 diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index a6b76b25bfd48..c5a1488588e97 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -561,7 +561,9 @@ def call_reject_if(association_name, attributes) end def raise_nested_attributes_record_not_found!(association_name, record_id) - raise RecordNotFound, "Couldn't find #{self.class._reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" + model = self.class._reflect_on_association(association_name).klass.name + raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}", + model, 'id', record_id) end end end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 9fef55adeaaa8..009b2bad57aa1 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -85,7 +85,8 @@ def find_by(arg, *args) def find_by!(arg, *args) where(arg, *args).take! rescue RangeError - raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range value" + raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value", + @klass.name) end # Gives a record (or N records if a parameter is supplied) without any implied