Skip to content

Instantly share code, notes, and snippets.

@turadg
Last active May 14, 2019 06:04
Show Gist options
  • Save turadg/5570181 to your computer and use it in GitHub Desktop.
Save turadg/5570181 to your computer and use it in GitHub Desktop.
Handle only 404s dynamically. It uses a normal controller and route for 404s, letting everything else go to the Rails default /public error pages. In my case it was to use the subdomain logic in my ApplicationController.
module MyApp
class Application < Rails::Application
require Rails.root + 'lib/custom_public_exceptions'
config.exceptions_app = CustomPublicExceptions.new Rails.public_path
end
end
class CustomPublicExceptions < ActionDispatch::PublicExceptions
def call(env)
status = env["PATH_INFO"][1..-1]
if "404" == status
# handle just 404 in our routes
MyApp::Application.routes.call env
else
super env
end
end
end
class ErrorsController < ApplicationController
skip_before_filter :authenticate_user! # if using Devise
def not_found
end
end
Geknowm::Application.routes.draw do
match "/404", :to => "errors#not_found"
end
@henrik
Copy link

henrik commented Aug 8, 2014

Thanks for this. In Rails 4 you need

match "/404" => "errors#not_found", via: [ :get, :post, :patch, :delete ]

And in case someone misses it, "MyApp" above should be whatever module you define in config/application.rb.

You may need to remove public/404.html so it doesn't appear of your custom action.

To see the page in dev, just visit /404. Or change config/environments/development.rb to say

config.consider_all_requests_local = false

but make sure you don't keep it. For one thing, it makes for a lot less helpful errors in dev.

@henrik
Copy link

henrik commented Aug 8, 2014

Wrote up my modifications as a blog post: http://thepugautomatic.com/2014/08/custom-404-page-with-rails-4/

@codeanpeace
Copy link

@henrik Was that intentional? xD

@mdeering
Copy link

@henrick I hope that link to a nginx 404 was in fact intentional got a good chuckle from that.

@dhulihan
Copy link

@tomprats
Copy link

tomprats commented Nov 5, 2015

Pretty great, one simple change is to use Rails.application.routes.call env instead of MyApp::Application.routes.call env so that you don't have to change that line to your application

@tannguyeneastagile
Copy link

class CustomPublicExceptions < ActionDispatch::PublicExceptions

  def call(env)
    status      = env["PATH_INFO"][1..-1]

    if "404" == status
      # handle just 404 in our routes
      MyApp::Application.routes.call env
    else
      super env
    end
  end

end

Can you write spec for this?

@SunDi3yansyah
Copy link

how, if I want to call the page can not be found on another controller to provide the conditions?

if no_session.nil?
  # how to call 404 page
  return false
else
  return true
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment