Home > Back-end >  Is it possible to customise a existing error/exception in rails?
Is it possible to customise a existing error/exception in rails?

Time:08-31

My controller is catching the following error in a observed case

#<ActiveRecord::RecordNotUnique: Mysql2:: Error: Duplicate entry 'xyz1' for key 'abc.xyz': INSERT INTO'abc' (<insert statement which is throwing the error>

I wanted to know if there is a way to customize this exception such that it also includes the existing entry because of which the error of duplication is being thrown..

It might seem redundant to modify an existing standard error/exception, but I need it to avoid repetition of same logic in every controller to handle this error in order to fulfill the requirement as stated above.

Update 1 Expected output:

Whenever the following exception is thrown, an alternate error message has to be sent as exception which will be something like this..

{Message: "Error caused due to Duplicate entry 'xyz1' for key 'abc.xyz'", existing_abc_with_same_xyz: Abc.find_by(xyz: "xyz1"}

Something like overriding/overloading the existing error statement.

There are many locations where this error is being handled because of Abc being a nested_attribute for many other resources... Because of which I will have to customise in every location, which I feel as redundant.

CodePudding user response:

You can use validation. It provides human readable error in the model

class Abc < ApplicationRecord
  validates :xyz, uniqueness: true
end

And then customize message in locales

Also it's possible to use :message key

validates :xyz,
  uniqueness: {
    message: ->(_, data) do 
      "Error caused due to Duplicate entry #{data[:value]} for key 'abc.xyz'. Existing Abc with same xyz: #{Abc.find_by(xyz: data[:value]}"
    end
  }

Please see guide

CodePudding user response:

You will need to validate with a custom validation class.

class User < ApplicationRecord
  validates_with MyUniquenessValidator
end

to save yourself time and effort, your custom validation class can inherit from the standard uniqueness validator, and just overwrite the pieces you need to customize.

# my_uniqueness_validator.rb
class MyUniquenessValidator < ActiveRecord::Validations::Uniqueness
  def validates_each # overwrites standard method
     # in here, copy the standard method, but change the line
     # where it looks for a duplicate to return the id of the duplicate
     # and change the line where it says record.errors.add(...) to include the id of the
     # record that is being duplicated
  end
end

You can probably find the standard ActiveRecord uniqueness validator to study by opening activerecord in your editor: bundle open activerecord and then navigate to 'lib/activerecord/validations/uniqueness.rb'. This is where to find it in Rails 7, it will be similar in Rails 5.

  • Related