はじめに
こんにちは、かるめと申します。
今回はRailsのViewレイアウトの選ばれ方についてまとめました。
デフォルトの挙動
Railsには、コントローラーに対応する名前のレイアウトファイルを自動的にapp/views/layouts/ディレクトリから探すという規約があります。
そこで見つからなかった場合にapp/views/layouts/application.html.erbが使用されます。
# app/views/layouts/photos.html.erbがあれば使用され、
# なかったらapp/views/layouts/application.html.erbが使用される
class PhotosController < ApplicationController
end
レイアウトを明示的に指定する
規約に任せず、使用するレイアウトファイルを明示的に指定することもできます。
layoutメソッドで指定
layoutメソッドを使用するとそのコントローラーで使用するレイアウトを指定できます。
class ErrorsController < ApplicationController
# app/views/layouts/application.html.erbではなく
# app/views/layouts/error.html.erbを使用する
layout "error"
def not_found
render formats: :html, status: :not_found
end
end
onlyやexceptを使用して、特定のアクションだけレイアウトを切り替えることもできます。
layout "error", only: %i[not_found]
renderメソッドで指定
renderメソッドのlayoutオプションを使用すると、そのrenderだけで使用するレイアウトを指定できます。
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
private
def render_not_found
# app/views/errors/not_found.html.erb をViewとして描画して、
# app/views/layouts/error.html.erb をレイアウトとして使用する
render "errors/not_found",
layout: "error",
formats: :html,
status: :not_found
end
end
layoutとrender layout:の違い
layoutメソッドは、基本的にコントローラー単位・アクション単位で使用するレイアウトを指定します。
layout "error"
renderメソッドのlayoutオプションでは、その1回のrenderで使用するレイアウトを指定します。
render ..., layout: "error"
そのため、コントローラー全体で同じレイアウトを使用するのであればlayoutメソッド、例外処理などで特定のrenderだけ別レイアウトを使用したい場合は、renderのlayoutオプションを使うのがよさそうです。
おわりに
ヘッダーやサイドバーなど一部の要素を切り替えるだけであればcontent_forでも可能ですが、その場合はapp/views/layouts/application.html.erbの可読性が落ちるので、うまく使い分けたいです。
参考