この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
こんにちは。T氏です。 今日はRailsのエラー画面(public/404.htmlや500.html)への遷移はどうやってされているかをご紹介します。
エラー画面への制御は、actionpackのrescue.rbで行っています。
*今回はactionpack-2.1.2である事前提に話を進めます。
では、処理が行われている実際のコードを抜き出して見てみましょう。
まず、Exceptionが発生するとrescue.rbのrescue_actionが呼び出されます。
ここではlocalhostか判定をして表示するviewの振り分けをしています。
def rescue_action(exception)
# logへの出力
log_error(exception) if logger
erase_results if performed?
# Let the exception alter the response if it wants.
# For example, MethodNotAllowed sets the Allow header.
if exception.respond_to?(:handle_response!)
exception.handle_response!(response)
end
# ここで判定をして、表示するエラー画面を切り分けている
if consider_all_requests_local || local_request?
# localhostだとこちら
rescue_action_locally(exception)
else
# public以下の[status_code].htmlが呼ばれる
rescue_action_in_public(exception)
end
end
次にlocalhostの場合に呼び出されるrescue_action_locallyを見てみましょう。
開発中によく見かけるエラー画面を出力しています。
def rescue_action_locally(exception)
add_variables_to_assigns
# インスタンスに対してエラー文言やファイル名等をセットしている
@template.instance_variable_set(“@exception”, exception)
@template.instance_variable_set(“@rescues_path”, File.dirname(rescues_path(“stub”)))
@template.send!(:assign_variables_from_controller)
@template.instance_variable_set(“@contents”, @template.render_file(template_path_for_local_rescue(exception), false))
# content_typeの指定
response.content_type = Mime::HTML
# rescues_pathではrescue.rbがあるディレクトリの下にあるlayout.erbを呼び出している
render_for_file(rescues_path(“layout”), response_code_for_rescue(exception))
end
最後に、rescue_action_in_publicメソッドを見てみましょう。
ここではファイル指定( [RAILS_ROOT]/public/[STATUS_CODE].html )をしています。
def rescue_action_in_public(exception) #:doc:
render_optional_error_file response_code_for_rescue(exception)
end
def render_optional_error_file(status_code)
status = interpret_status(status_code)
# pathとファイル名を指定している
path = “#{Rails.public_path}/#{status[0,3]}.html”
if File.exist?(path)
# renderするファイルとステータスコードを指定
render :file => path, :status => status
else
head status
end
end
以上がRailsのエラー画面への制御でした。