27

I've got a requirement to specify a named route in a Ruby on Rails project that returns the public/404.html page along with the 404 server response code.

Leaving it blank is not an option, please don't question why, it just is :) It absolutely must be a named route, or a map.connect entry would do.

Something like this would be great:

map.my_named_route '/some/route/', :response => '404'

Anyone have any idea what's the easiest way to do something like this. I could create a controller method which renders the 404.html file but thought there might be an existing cleaner way to do this. Looking forward to any responses - thanks,

Eliot

Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
Eliot Sykes
  • 9,616
  • 6
  • 50
  • 64

4 Answers4

54

You can route to a rack endpoint (rails 3) that vends a simple 404:

match 'my/route', to: proc { [404, {}, ['']] }

This is particularly handy, for example, to define a named route to your omniauth endpoint:

match 'auth/:action', to: proc { [404, {}, ['']] }, as: :omniauth_authorize
Community
  • 1
  • 1
Nevir
  • 7,951
  • 4
  • 41
  • 50
  • This is a good approach for any response that does not need a controller. It is still less efficient than doing this in Apache/nginx. – mmell May 29 '13 at 16:41
  • 7
    In Rails 4 use the :to option, e.g. `get '/apple-touch*str', to: proc { [404, {}, ['']] }` – mmell May 29 '13 at 16:41
  • 3
    @mmell That won't work, you have to do this: `get '/:str', to: proc { [404, {}, ['']] }, constraints: { str: /apple-touch.*/}` – Amala Jul 22 '15 at 01:47
3

In your routes.rb:

map.my_404 '/ohnoes', :controller => 'foobar', :action => 'ohnoes'

In FoobarController:

def ohnoes
  render :text => "Not found", :status => 404
end

If you need to render the same 404 file as a normal 404, you can do that with render :file.

See ActionController::Base documentation for examples.

Luke Francl
  • 31,028
  • 18
  • 69
  • 91
2

Why dont you do this in Apache/nginx where you use mod_rewrite (or however nginx does rewrites) to link to a non-existent page or instead send a 410 (Gone, no longer exists) Flag?

Anyway, if you want the rails app to do this, I think the way is as you suggested, create a named route to an action that does a render(:file => "#{RAILS_ROOT}/public/404.html", :status => 404)

Omar Qureshi
  • 8,963
  • 3
  • 33
  • 35
1

Slighly shorter version than the previous answers to 404 any get in one line. get '*_', to: ->(_) { [404, {}, ['']] }

BookOfGreg
  • 3,550
  • 2
  • 42
  • 56