Currently in production im getting this text:
500 Internal Server Error
If you are the administrator of this website, then please read this web application\'
Here is latest and quick fix for showing custom 404_error page.
config.exceptions_app = self.routes
config.consider_all_requests_local = false
The Error you are experiencing is being thrown from
https://github.com/rails/rails/blob/4-0-stable/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L18-L22
This means, the code your exceptions are getting rescued by are themselves throwing exceptions. You can check your logs for text:
Error during failsafe response:
to identify what the exceptions really are originating from and thus solve your problem.
Error pages in application should be as simple as it possible. Same recommendation concerns their rendering. If your application returns 500 HTTP response code it means that things got wrong already. And there is a chance you could not render error page and display it to user.
Ideally error pages should be a plain HTML served directly by your web server without hitting application server.
Speaking of Rails implementation of this idea. It based on using asset pipeline for precompiling the HTML static pages.
Firstly add new assets type (Rails > 4.1):
# config/initializers/assets.rb
Rails.application.config.assets.precompile += %w(404.html 500.html)
Rails.application.config.assets.paths << Rails.root.join('app/assets/html')
Rails.application.config.assets.register_mime_type('text/html', '.html')
If templating engine is using (e.g. slim, haml), register it via initializer:
# for Slim
Rails.application.assets.register_engine('.slim', Slim::Template)
# for Haml
Rails.application.assets.register_engine('.haml', Tilt::HamlTemplate)
Now you ready to create pretty error pages in app/assets/html directory using your favorite template engine and Rails built-in view helpers.
On production asset pipeline adds digest to compiled assets and stores files under default folder (typically shared/public/assets on production server). You can use capistrano to copy error pages to web server root:
# config/deploy.rb
# Capistrano 3 only
namespace :deploy do
desc 'Copy compiled error pages to public'
task :copy_error_pages do
on roles(:all) do
%w(404 500).each do |page|
page_glob = "#{current_path}/public/#{fetch(:assets_prefix)}/#{page}*.html"
# copy newest asset
asset_file = capture :ruby, %Q{-e "print Dir.glob('#{page_glob}').max_by { |file| File.mtime(file) }"}
if asset_file
execute :cp, "#{asset_file} #{current_path}/public/#{page}.html"
else
error "Error #{page} asset does not exist"
end
end
end
end
after :finishing, :copy_error_pages
end
And last thing. Tell web server to use these files for certain HTTP error codes (sample nginx configuration):
error_page 500 502 503 504 /500.html;
error_page 404 /404.html;
For Sprocket 3 you need something like this (tested with Rails 5):
# config/environments/production.rb
config.assets.configure do |env|
env.register_transformer 'text/slim', 'text/html', Slim::Template
env.register_mime_type 'text/slim', extensions: ['.html']
env.register_engine '.slim', Slim::Template
end
# config/initializers/assets.rb
Rails.application.config.assets.precompile += %w(404.html 500.html)
Rails.application.config.assets.paths << Rails.root.join('app/assets/html')