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
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 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.
Is there are way to tell Rails to render your custom error pages (for example, the ones you write in your ErrorsController)? I've searched many topics, and the one that seems to kinda work was to add to your ApplicationController something like
if Rails.env.production?
rescue_from Exception, :with => :render_error
rescue_from ActiveRecord::RecordNotFound, :with => :render_not_found
rescue_from ActionController::UnknownController, :with => :render_not_found
rescue_from ActionController::UnknownAction, :with => :render_not_found
end
and then you write your methods render_error and render_not_found the way you want. This seems to me like a really unelegant solution. Also, it's bad, because you have to know exactly what are all the errors that could happen. It's a temporary solution.
Also, there is really no easy way to rescue an ActionController::RoutingError that way. I saw that one way was to add something like
get "*not_found", :to => "errors#not_found"
to your routes.rb. But what if you want to raise somewhere an ActionController::RoutingError manually? For example, if a person who is not an administrator tries to go to "adminy" controllers by guessing the URL. In those situations I prefer raising a 404 more than raising an "unauthorized access" error of some kind, because that would actually tell the person that he guessed the URL. If you raise it manually, it will try to render a 500 page, and I want a 404.
So is there a way to tell Rails: "In all cases you would normally render a 404.html or a 500.html, render my custom 404 and 500 pages"? (Of course, I deleted the 404.html and 500.html pages from the public folder.)
Unfortunately there aren't any methods I know of that can be overridden to provide what you want. You could use an around filter. Your code would look something like this:
class ApplicationController < ActionController::Base
around_filter :catch_exceptions
protected
def catch_exceptions
yield
rescue => exception
if exception.is_a?(ActiveRecord::RecordNotFound)
render_page_not_found
else
render_error
end
end
end
You can handle each error as you see fit in that method. Then your #render_page_not_found and #render_error methods would have to be something like
render :template => 'errors/404'
You would then need to have a file at app/views/errors/404.html.[haml|erb]
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.
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.