I am trying to setup a custom error page in my website. I am following the guidelines atPerfectLine Blog.
It works in the case where the controller exists, but the id does not exist. For example, I have a blog controller and id 4 does not exist. It shows the custom error page
But it does not exist in the case, where controller itself does not exist. For example, if I type some random controller with a numeric id does not gets caught by the methods I have setup in the application controller to re-route the custom error pages. In this case, I get an
ActionController::RoutingError (No route matches "/randomcontrollername"):
in the terminal and the default error page that comes with rails.
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
unless Rails.application.config.consider_all_requests_local
rescue_from Exception, :with => :render_error
rescue_from ActiveRecord::RecordNotFound, :with => :render_not_found
rescue_from ActionController::RoutingError, :with => :render_not_found
rescue_from ActionController::UnknownController, :with => :render_not_found
rescue_from ActionController::UnknownAction, :with => :render_not_found
end
private
def render_not_found(exception)
render :template => "/error/404.html.erb", :status => 404
end
def render_error(exception)
render :template => "/error/500.html.erb", :status => 500
end
end
Could you please help me. Thanks.
You can do that with route globbing in rails, It lets you match any action to any part of a route using wildcards.
To catch all remaining routes, just define a low priority route mapping as the last route in config/routes.rb:
In Rails 3:
match "*path" => 'error#handle404'
In Rails 2:
map.connect "*path", :controller => 'error', :action => 'handle404'
params[:path] will contain the matching part.
If you don't need dynamic error pages, just edit public/404.html and public/505.html. If you do, see Reza.mp's answer.
Related
I am working on a Rails app. In my app, if I enter a custom route manually in the address bar/ as URL which is not present in config/routes.rb, it will show up the below given error message.
Routing Error
No route matches "/clientImage/blablahblah"
I want this to be redirected to a proper display for all the wrong routes given by the user either intentionally/unintentionally. Any help would be greatly appreciated.
When someone enters unsupported url Rails will raise ActionController::RoutingError. You can rescue this error and render 404 Not Found html.
Rails provides some special function called rescue_from for this purpose.
class ApplicationController < ActionController::Base
rescue_from ActionController::RoutingError, :with => :render_not_found
rescue_from StandardError, :with => :render_server_error
protected
def render_not_found
render "shared/404", :status => 404
end
def render_server_error
render "shared/500", :status => 500
end
end
Put your 404.html, 500.html in app/views/shared
Yourapp::Application.routes.draw do
#Last route in routes.rb
match '*a', :to => 'errors#routing'
end
The "a" is actually a parameter in the Rails 3 Route Globbing technique. For example, if your url was /this-url-does-not-exist, then params[:a] equals "/this-url-does-not-exist". So be as creative as you'd like handling that rogue route.
In app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
def routing
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
end
end
I have one rails application in which I have two sections, so I want to use two different layouts for the Error page.
For example, if an error is coming from Section 1 then layout1 / different page should be used for the Error (404, 500).
If error is coming from Section 2 then layout2 / different page should be used for the Error (404, 500).
I've written code to define the Error page, enabled with erb and ruby code.
in application.rb
config.exceptions_app = self.routes
in routes.rb
match "/404", :to => "errors#error_404"
match "/500", :to => "errors#error_500"
Updated
Thought about it a little. If you only have a few types of errors, how about doing it like this?
In your routes.rb, at the very last line, add a
match '/my_segment/*path', :to => 'errors#not_found'
This should match any path that is not defined (which normally throws ActionController::RoutingError) and push it to your global error page.
You can play with play with the segments wildcard above to get your correct path. This should NOT affect your predefined paths, like mydomain.com/controller1.
Below is a more fine grained method of control.
This will help you match any errors from mydomain.com/some_controller/bad_params
def firstController < ApplicationController
def method_in_first_controller
# Do something here
rescue
#error = # Error object here
render :template=>"some_error_template", :status => :not_found # In specific action
end
end
def secondController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, :with => :rescue_not_found # In secondController
def method_in_second_controller
# Do something
end
protected
def rescue_not_found
#error = # Error object here
render :template => 'some_error_template', :status => :not_found
end
end
def ApplicationController
rescue_from ActiveRecord::RecordNotFound, :with => :rescue_not_found # Globally
protected
def rescue_not_found
#error = # Error object here
render :template => 'application/not_found', :status => :not_found
end
end
Using referrer doesn't seem to get anywhere, sorry for the bad answer yesterday.
In your errors controller you can have a check who is the referrer and have a conditional layout based on that
i was wondering if i could add an exception to route globbing in rails. in my routes.rb i have
unless params[:not_found].eql? 'admin_data'
match '*not_found', to: 'errors#error_404'
end
im trying to enforce custom error pages, except when a user visits
myapp.heroku.com/admin_data
it doesn't seem like fetching :not_found as a param works. is there a way to add an exception in routes.rb?
if it helps, in my errors_controller i have..
def error_404
#not_found_path = params[:not_found]
end
thank you
update.
i tried doing just
puts :not_found
puts %{not_found}
but doesn't seem to work either hmmm...im trying to see if i can retrieve the params from the user
It would be much more convenient to define allowed routes in routes.rb and add exception handling in application controller for routing error:
class ApplicationController < ActionController::Base
rescue_from ActionController::RoutingError, :with => :render_not_found
private
def render_not_found
render_error_page_for(404)
end
def render_error_page_for(code)
respond_to do |format|
format.html { render :file => "#{Rails.root}/public/#{code}.html", :status => code, :layout => false }
end
end
i do catch my exception handling in my application controller but unfortunately for admin_data, i don't explicitly set it in routes.rb. it gets configured somewhere in the gem with namespace or something (im not really sure)
but on a positive note... i finally fixed it! i changed my glob and did...
match '*not_found', to: 'errors#error_404', :constraints => {:subdomain => "!(admin_data.)"}
to ignore everything which uses admin_data.
I am looking to use rails to redirect links that I am sure are out there on the internet from an old domain of mine to a new one.
I would like to take address example.com/about ( about will not exist anymore)
and in my application_controller to take the 404, inspect the url and then redirect to
newexample.com/about
what's the best way to do this?
Add this to the end of your Routes file:
map.connect '*path', :controller => 'some_controller', :action => 'some_action'
This will catch any 404. Within the controller and action that will handle this route, use params[:path] to examine the url. Then you can redirect_to based on whatever is contained in params[:path].
You need to use rescue_from. In your ApplicationController, add something like:
rescue_from ActionController::RoutingError, :with => :redirect_missing
rescue_from ActionController::UnknownController, :with => :redirect_missing
rescue_from ActionController::UnknownAction, :with => :redirect_missing
def redirect_missing
redirect_to "http://newexample.com/about"
end
I am working on a RoR website and would like to handle server errors (400, 404, 500, etc.) individually. Also, since the website is dynamic I would like to handle the errors within the rails environment rather than at the server level.
An example of what I would like to do could be to present the user with optional material or a search bar when she bumps into a page or template that will not load or simply does not exist.
So, I did a bit of reading and I think that using the rescue_from exception handler is the way to go in my case. (Would be more than happy to hear if any of you have a different opinion).
I have a simple working prototype (see code below) up and running, however, I get an error when I include the following exception handler to the code:
rescue_from ActionController::MissingTemplate, :with => :not_found #404
Now, I can't see that I have a spelling error and I have seen this line in code posted on the web. However, when I include it I get the following routing error:
Routing Error No route matches "/errorhandle" with {:method=>:get}
I am working on rails 2.3.5, perhaps that has got something to do with it?
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery #See ActionController::RequestForgeryProtection for details
#ActiveRecord exceptions
rescue_from ActiveRecord::RecordNotFound, :with => :not_found #400
#ActiveResource exceptions
rescue_from ActiveResource::ResourceNotFound, :with => :not_found #404
#ActionView exceptions
rescue_from ActionView::TemplateError, :with => :not_found #500
#ActionController exceptions
rescue_from ActionController::RoutingError, :with => :not_found #404
rescue_from ActionController::UnknownController, :with => :not_found #404
rescue_from ActionController::MethodNotAllowed, :with => :not_found #405
rescue_from ActionController::InvalidAuthenticityToken, :with => :not_found #405
rescue_from ActionController::UnknownAction, :with => :not_found #501
# This particular exception causes all the rest to fail.... why?
# rescue_from ActionController::MissingTemplate, :with => :not_found #404
protected
def not_found
render :text => "Error", :status => 404
end
# Scrub sensitive parameters from your log
# filter_parameter_logging :password
end
Take a quick look at these:
http://www.ruby-forum.com/topic/47898
http://henrik.nyh.se/2008/09/404-invalid-rails-format
In particular, a post in the first link:
You can't use a regular 'rescue' keyword to rescue MissingTemplate
exception.
Use rescue_action instead, for example:
def rescue_action(exception)
if ::ActionController::MissingTemplate === exception
render :text => 'rescued'
else
super
end
end
Kent.