rescue_from ActionController::RoutingError in Rails 4
Asked Answered
D

4

27

I've got the following error:

ActionController::RoutingError (No route matches [GET] "/images/favicon.ico")

I want to show error404 page for links that are not existing.

How can I achieve that?

Devotional answered 15/9, 2014 at 5:33 Comment(0)
P
63

In application_controller.rb add the following:

  # You want to get exceptions in development, but not in production.
  unless Rails.application.config.consider_all_requests_local
    rescue_from ActionController::RoutingError, with: -> { render_404  }
  end

  def render_404
    respond_to do |format|
      format.html { render template: 'errors/not_found', status: 404 }
      format.all { render nothing: true, status: 404 }
    end
  end

I usually also rescue following exceptions, but that's up to you:

rescue_from ActionController::UnknownController, with: -> { render_404  }
rescue_from ActiveRecord::RecordNotFound,        with: -> { render_404  }

Create the errors controller:

class ErrorsController < ApplicationController
  def error_404
    render 'errors/not_found'
  end
end

Then in routes.rb

  unless Rails.application.config.consider_all_requests_local
    # having created corresponding controller and action
    get '*path', to: 'errors#error_404', via: :all
  end

And the last thing is to create not_found.html.haml (or whatever template engine you use) under /views/errors/:

  %span 404
  %br
  Page Not Found
Ponzo answered 15/9, 2014 at 6:34 Comment(5)
This doesn't work in Rails 4.2.5. I'm guessing that's because the exception is raised by ActionDispatch before any controller code is run.Jackass
@Jackass I wrote it in the times of Rails 4.0.x, but have just tested it with Rails 4.2.5 - I suppose you did not add route and did not create the errors_controller.rb :) If that is the case - please be sure to retract the downvote, unless you have more reasons to leave itPonzo
Sorry, I didn't set up the route correctly. But why have, rescue_from ActionController::RoutingError, with: -> { render_404 } if you're routing directly to the action?Jackass
If you need to catch this before any Controller code is run (i.e. on the Routes level), see @misu's answer below for adding match '*path' => 'errors#error_404', via: :all.Lyrate
How can you get a ActionController::RoutingError when you have a path that matches everything (get '*path', to: 'errors#error_404', via: :all) ?Formfitting
C
10

@Andrey Deineko, your solution seems to work only for the RoutingErrors raised manually inside a conrtoller. If I try it with the url my_app/not_existing_path, I still get the standard error message.

I guess this is because the application doesn't even reach the controllers, since Rails raises the error before.

The trick that solved the problem for me was to add the following line at the end of the routes:

Rails.application.routes.draw do
  # existing paths
  match '*path' => 'errors#error_404', via: :all
end

to catch all not predefined requests.

Then in the ErrorsController you can use respond_to to serve html, json... requests:

class ErrorsController < ApplicationController
  def error_404
    @requested_path = request.path
    repond_to do |format|
      format.html
      format.json { render json: {routing_error: @requested_path} }
    end
  end
end
Cass answered 2/11, 2016 at 10:28 Comment(3)
could you explain @requested_path = request.path and its corresponding call format.json { render json: {routing_error: @requested_path} }?Lesslie
I've just used @requested_path in the template (error_404.html.haml). As for the json, if I'm sure I don't want a full page returned, for example by ajax, I can ask for json returned, and get the error messageCass
@misu this works perfect, your trick of adding this in the config/routes.rb file was the keyLyrate
Q
1

Copying favicon image in app/assets/images worked for me.

Qualifier answered 28/1, 2015 at 14:14 Comment(0)
R
0

In Rails 7 (2023)

  1. config/routes.rb

    Rails.application.routes.draw do

    match '*path' => 'errors#error_404', via: :all

    end

  2. controllers/errors_controller.rb

    class ErrorsController < ApplicationController

    def error_404

     render template: 'pages/not_found', status: 404 
    

    end

    end

  3. pages/not_found.html.erb

Error 404

Page not found

... but you are losing all active_storage images!!!

Ratel answered 21/3, 2023 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.