I wanted to find the best way to handle errors in rails, so my code is easy to read and my tests too.
Firstly, I created an errors.rb
file in the /lib folder.
class Errors
# When they don't have permission to do something
class Forbidden < StandardError; end
# When something they want is not found
class NotFound < StandardError; end
# When the input is somehow bad
class InvalidParameters < StandardError; end
end
At the top of my application_controller.rb
I loaded that file (require ‘errors’). Then in my application controller I added the code below to rescue from my exceptions.
rescue_from Errors::Forbidden do
not_found
end
rescue_from Errors::NotFound do
bad_request
end
rescue_from Errors::InvalidParameters do
bad_request
end
def not_found
respond_to do |format|
format.html do
render file: "#{Rails.root}/public/404.html",
layout: false, status: :not_found
end
format.any do
head :not_found
end
end
end
def bad_request
respond_to do |format|
format.html do
render file: "#{Rails.root}/public/422.html",
layout: false, status: :unprocessable_entity
end
format.any do
head :unprocessable_entity
end
end
end
Now I can raise an exception in my controllers like so:
def update
load_application
raise Errors::NotFound unless @application.valid?(:applicant_check)
if @application.save!
flash.notice = 'Terms emailed to applicant'
ApplicantTermsMailer.terms_email(@application).deliver_later
redirect_to action: 'show' and return
end
render 'show'
end
This is really easy to test, using mini test.
test 'terms fail to send out as applicant name and/or email not found' do
sign_in users(:batman)
patch application_terms_url(application_id: @application.id)
assert_response :unprocessable_entity
end
Finally I just need to make my error pages look good.