Where to define custom error types in Ruby and/or Rails?
For Gems
I have seen many times that you define exceptions in this way:
gem_dir/lib/gem_name/exceptions.rb
and defined as:
module GemName
class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
end
an example of this would be something like this in httparty
For Ruby on Rails
Put them in your lib/ folder under a file called exceptions.rb, which would look something like this:
module Exceptions
class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
end
and you would use it like this:
raise Exceptions::InvalidUsername
Custom error pages in Ruby on Rails
The rescue_from
method can be used for global exception handling.
Change theapp/controller/application_controller.rb
file to add the exception handler.
class ApplicationController < ActionController::Base
rescue_from ::PermissionDenied, :with => :render_permission_denied
def render_permission_denied(e)
@error = e # Optional, accessible in the error template
log_error(e) # Optional
render :template => 'error_pages/permission_denied', :status => :forbidden
end
end
Now add a haml file called permission_denied.html.haml
in app/views/error_pages
directory.
%h1 Permission Denied!
%p #{@error.message}
Refer to the rails documentation for more details.
Rails 4 Custom Error Handling for Specific ContentTypes
Although your question is not directly clear, here's what I'd be looking at...
--
Error Handling
We handle custom error pages using the config.exceptions_app
middleware hook
We've written a gem for it called exception_handler
& have a popular answer here. There's also a great github gist here
I would recommend using the exceptions_app
middleware hook, with an accompanying controller to capture & respond to the errors:
# config/environments/development.rb
config.consider_all_requests_local = false # true -> for testing
#config/application.rb
config.exceptions_app = ->(env) { ExceptionController.action(:show).call(env) }
#app/controllers/exception_controller.rb
Class ExceptionController < ApplicationController
respond_to :js, :json, :html
def show
@exception = env['action_dispatch.exception']
@status_code = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
@rescue_response = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
respond_with @rescue_response
end
end
This will allow you to create the custom pages you need, as well as being able to return the required mime
types
--
respond_to
As a general rule, Rails allows you to use the respond_to
code block to deliver different responses to different mime
types
You can use the block in two ways:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
def your_action
respond_to do |format|
format.json
format.html
end
end
end
Alternatively, you can use the respond_to
& respond_with
methods in tandem:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
respond_to :js, :json, :html
def your_action
@your_variable = "test"
respond_with @your_variable #-> responds with appropriate mime-type
end
end
--
Responses
If you want to issue a JSON-only response, you need to use all of the above code to create a controller which allows you to pass the JSON response.
You must remember that JSON responses are just a type of data response -- specifically, just providing a nested hash of all the data you respond with.
If you want to receive a JSON response to your errors, you basically need to be able to create a controller to handle the correct mime-type. What I've recommended above will do that for you
Rails custom error Logging
You could capture errors within the ApplicationController with rescue_from and then write the error to a log before re-raising the error.
class ApplicationController < ActionController::Base
rescue_from StandardError, with: :log_error
private
def log_error(e)
error_log.info(e.message)
raise(e)
end
def error_log
@error_log ||= Logger.new(Rails.root.join('log', "error-#{Rails.env.to_s}.log"))
end
end
How to include Custom exception in Rails?
First, I think that you're raising your exception incorrectly.
In your custom exception class, your initialize method takes in arguments. Therefore you should raise it with:
raise CustomError.new(arg1, arg2, etc.)
Read this.
Lastly, don't rescue from StandardError if CustomError is a child of StandardError; otherwise your manual 'raise' will be rescued.
How create custom exception (Including explicitly the control of values null) and save all exceptions in log file in Rials 5.2
class YourCustomError < StandardError
attr_accessor :message
def initialize(message)
@message = message
end
def to_s
"[#{message}] #{super}"
end
end
That's how to create your own Error class. And then
begin
serie_num = (game_number..Constants::LAST_NUMBER_FIZZBUZZ).to_a
rescue YourCustomError => e
#Use logging lib to log or do custom error handling
end
And in your custom method whenever you regard as the error, do this.
raise YourCustomError.new("Error Occured. Contact the System Admin") # the message can be anything specific to your business domain's problem.
Convention for the location of error classes in a rails application
as you did not talk about the version of rails that you are using, i will be referring to rails4.
starting with rails 3 (i think) every folder under app
will get autoloaded. with this in mind, just put stuff where it belongs app/exceptions
app/worker
app/whetever
.
from my perspective, exceptions are a little different. they usually have some kind of context. that's why i like them to be in some module ie Authorization::NotAuthorized
.
so in my case, there would be a concern named Authorization
that holds this error class.
Custom Error Pages in Rails?
I would suggest using exceptions to render such error pages, so you can use inheritance to group your error messages...
First, declare some (I usually do it in application_controller.rb)
class Error404 < StandardError; end
class PostNotFound < Error404; end
Then add code to ApplicationController to handle them
class ApplicationController < ActionController::Base
# ActionController::RoutingError works in Rails 2.x only.
# rescue_from ActionController::RoutingError, :with => :render_404
rescue_from Error404, :with => :render_404
rescue_from PostNotFound, :with => :render_post_not_found
def render_404
respond_to do |type|
type.html { render :template => "errors/error_404", :status => 404, :layout => 'error' }
type.all { render :nothing => true, :status => 404 }
end
true
end
def render_post_not_found
respond_to do |type|
type.html { render :template => "errors/shop_not_found", :status => 404, :layout => 'error' }
type.all { render :nothing => true, :status => 404 }
end
true
end
end
This renders errors/error_404 with the errors layout. Should get you started :)
And in your target_controller:
raise PostNotFound unless @post
Edit
Note for Rails 3
for a longer explanation on why ActionController::RoutingError doesn't work for rails 3:
Rails 3.0 Exception Handling.
Rails ticket 4444
"If your application relies on engines that extend your app with their
own routes, things will break because those routes will never get
fired!"
Custom error pages for 404, 500 but where is the default 500 error message coming from?
The error you are experiencing is being thrown from
https://github.com/rails/rails/blob/4-0-stable/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L18-L22
This means the code your exceptions are getting rescued by are themselves throwing exceptions.
You can check your logs for text:
Error during failsafe response:
to identify what the exceptions really are originating from and thus solve your problem.
Related Topics
Looping Through an Array with Step
Ruby on Rails Rake Assets:Precompile Error
Rails on Windows - Install Issue
How to Dynamically Alter Inheritance in Ruby
Add "# Coding: Utf-8" to All Files
Do Ruby 'Require' Statements Go Inside or Outside the Class Definition
Differencebetween Link_To, Redirect_To, and Render
Asynchronous Http Request in Ruby
(Ruby) Getting Net::Smtp Working with Gmail...
How to Run Ruby and Git Commands in One Place on Windows
Actionview::Template::Error (Incompatible Character Encodings: Utf-8 and Ascii-8Bit)
Rails - Whenever Gem - Dynamic Values
How to Set Http_Referer When Testing in Rails
Differencebetween 'Range#Include' and 'Range#Cover'