Reputation: 1974
When record is not found I render 404 page. The problem is it's doesn't have application
layout although 403
works fine
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :render_404
def render_404
render file: 'public/404.html', status: 404, layout: 'application'
end
def render_403
render file: 'public/403.html', status: 403, layout: 'application'
end
end
Upvotes: 1
Views: 181
Reputation: 76774
We have a better way of capturing exceptions:
(Here's where we got it from)
Capture
A much more efficient way of capturing exceptions is to use the exceptions_app
method
#config/environments/production.rb
config.exceptions_app = ->(env) { ExceptionController.action(:show).call(env) }
--
Process
Secondly, you should process the caught exception. You can do this by sending the request to a controller method (we use ExceptionController#show
):
#app/controllers/exception_controller.rb
class ExceptionController < ApplicationController
#Response
respond_to :html, :xml, :json
#Dependencies
before_action :status
#Layout
layout :layout_status
####################
# Action #
####################
#Show
def show
respond_with status: @status
end
####################
# Dependencies #
####################
protected
#Info
def status
@exception = env['action_dispatch.exception']
@status = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
@response = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
end
#Format
def details
@details ||= {}.tap do |h|
I18n.with_options scope: [:exception, :show, @response], exception_name: @exception.class.name, exception_message: @exception.message do |i18n|
h[:name] = i18n.t "#{@exception.class.name.underscore}.title", default: i18n.t(:title, default: @exception.class.name)
h[:message] = i18n.t "#{@exception.class.name.underscore}.description", default: i18n.t(:description, default: @exception.message)
end
end
end
helper_method :details
####################
# Layout #
####################
private
#Layout
def layout_status
@status.to_s == "404" ? "application" : "error"
end
end
--
Show
Finally, you can output the message you've received, with custom layouts per error:
#app/views/exception/show.html.erb
<div class="box">
<h1><%= details[:name] %></h1>
<p><%= details[:message] %></p>
</div>
Upvotes: 1
Reputation: 2796
Are you sure your custom rescue_from is being executed?.. I don't think so.
Maybe another exception is thrown, not ActiveRecord::RecordNotFound
.
The thing is that public/404.html
is rendered for 404 error by rails by default, with no layout.
If you want to tweak this behavior, remove that public/*
files and put them under app/views
folder, so you have full control and rails default behavior won't confuse you.
Upvotes: 1