Where to Define Custom Error Types in Ruby And/Or Rails

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



Leave a reply



Submit