📝

RailsでViewをRenderingする仕組み

2021/03/03に公開

なに?

Controllerからどのようにしてテンプレートファイルを探索し、Renderingしているのかを調べた。

ばーじょん

  • Ruby ruby 2.7.2p137
  • Rails 6.1.2

ながれ

Controllerからrender等で明示的にレスポンスを設定しない場合、以下のようなフォーマットでファイル探索を行い、renderが実行される。

# variantは、スマートフォンやタブレットなど向けにviewを切り替えるときに使い、`request.variant = :tablet`のように指定する。
# localeやvariantsが一致しない場合、#{action_name}.#{extension}にフォールバックされる
app/views/#{namespace}/#{action_name}.#{locale}.#{format}+#{variants}.#{extension}

もし、variantsに一致するテンプレートファイルが見つからない場合、以下のようなエラーが発生する。

ActionController::UnknownFormat (DashboardsController#index is missing a template for this request format and variant.

request.formats: ["text/html"]
request.variant: [:tablet]):

さらに、テンプレートファイルが一切見つからない場合は、リクエストによって2つの処理に分かれる。

  • HTMLを求める通常のGETリクエスト(not XHR)の場合
    • 以下のエラーが発生
    • ActionController::MissingExactTemplate (DashboardsController#hoge is missing a template for request formats: text/html):
      
  • 上記以外
    • 以下のロガーをINFOレベルで出力し、head(204 No Content)を返す
    • No template found for DashboardsController#hoge, rendering head :no_content
      

テンプレートファイル内で、Controllerのインスタンス変数が使える理由は、ActionController::BaseActionView::Renderingincludeされているためだ。
このmoduleが、ControllerとViewの橋渡しのような役目をしている。
ActionController::APIは異なるので、要確認。

ActionViewでレスポンスボディが作られた後、Controllerのresponse_bodyにセットされる。

Discussion