【概要】
以前Railsでフォームの作成について解説しました。(詳細は下記。)
しかし、form_with
とセットで使用されるrender
について解説がなかったためにこちらで詳細を解説しようと思いました!
renderにも特殊な使い方があるので、少し混乱した箇所があるのですが、慣れると良いコードを書けるようになります。
こちら使い方をおさらいしておきましょう。
【環境】
この記事は下記の実行環境で動作確認しております。
・Rails 7.0.4
・Ruby 3.1.4
renderとは
例に倣って、render
を解説したいと思います。「render」とは、部分テンプレートを行うためのフレームワークとなっております。
まずは、下記をご覧ください。
def index
@posts = Post.all
render ’posts/index'# postsフォルダ内のindex.html.erbを表示
end
「render」から始まる記載がありますね。これは注釈にある通り、postフォルダのindexアクションを表示するためのものになります。
簡単にいうと、viewファイルを表示するために必要なメソッドであることがわかります。実際にコントローラではこのような処理でviewアクションに値を渡しているのですね。
但し、コントローラー
では下記の記述方法が一般的です。Railsのコントローラーにおけるアクションのデフォルト動作として、アクション名に対応するビューを自動的に探し、表示できるからです。
<!-- app/views/xxx_controller -->
def index
@posts = Post.all
end
そのためここでは、
viewファイルでのrender
の使用方法について解説したいと思います。(Controllerで使用するものについては省略します。)
rednerの使用方法
本題です。まずは、基本的な書き方について抑えましょう。
今回は、Itemsコントローラから新規作成するフォームがあることをイメージしてください。
<!-- app/items_controller.rb -->
class ItemsController < ApplicationController
def new
@item = Item.new
end
end
<!-- app/views/items/new.html.erb -->
<h1>Create a new item</h1>
<%= render 'form', item: @item %>
<!-- app/views/items/_form.html.erb -->
<%= form_for item do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit "Create Item" %>
</div>
<% end %>
_form.html.erb
というファイルが出てきました。これはパーシャルファイルと呼ばれるもので再利用できるviewファイルです。(部分テンプレートとも呼ぶ)
どういうことかというと、new
アクションとedit
アクションで同じフォームを使用したいと考えます。その場合に、パーシャルファイルを使うと再度記述する必要がないのと、メンテナンスの際に一箇所だけ修正を行えばいいので、保守性も高くなります。
パーシャルファイルの説明が済んだところで話を戻します。このファイルを利用するために必要なのがrender
というわけですね。new
の部分で使われているのが今回の話の根幹になります。
基本構文
#`1件の場合
<%= render 'form', ローカル変数名: @インスタンス変数名 %>
このようになります。ローカル変数名とインスタンス変数名はコントローラのインスタンス名と同じものを記載していただければ良いです。
では、なぜローカル変数を指定しているのでしょうか?
・スコープの明確化: ローカル変数を使用することで、パーシャル内の変数がどのように設定されているかが明確になります。ビュー内で変数のスコープがどのように制御されているかを理解しやすくなります。
・再利用性: ローカル変数を使うことで、パーシャルはそのまま他のビューに組み込むことができます。インスタンス変数ではなくローカル変数を使うことで、パーシャルの再利用性が高まります。
・名前の衝突の回避: ビュー内で同じ名前のインスタンス変数が複数存在する場合、パーシャル内部での変数の値が予測できなくなる可能性があります。ローカル変数を使用することで、名前の衝突を回避できます。(ChatGPTより引用。)
つまり、コードの明確化と、変数名の衝突を回避することができるためと考えてください。
難しい場合は、このように定義するんだな。と思ってくれれば構いません。
またフォームなどで複数件のインスタンスの情報が必要な場合は、下記のようになります。
#N件の場合
<%= render 'form', board: @board, comment: @comment %>
但し、使い分けが必要なこともあります。これらを実装順に整理しましょう。
indexの場合
まずはindexアクションについてです。
実装内容などについては、上記の条件と同じようにitems_controller
を参考に考えます。
まずは内容を確認しましょう。
collectionの渡し方
<%= render @items %>
パーシャル先の指定は下記のようになります。
<%= link_to item.title, item_path(item) %>
まず、先ほどの'form'
の内容が記述されてないのが気になりますね。あと、ローカル変数に値を渡さずに管理しています。
(ChatGPTの)解説をすると下記になります。
<%= render @boards %> という形式は、コレクション(例: 配列やActive Recordコレクション)を一括して表示する際に使用します。この場合、通常はパーシャルは必要ありません。
Railsは自動的に各要素に対して適切なビューファイルを探し、それを使ってコレクション内の各要素を描画します。
具体的には、例えば @boards がボードの配列である場合、Railsは_board.html.erb というパーシャルを自動的に探し、それを使用して @boards 内の各要素を描画します。
したがって、この場合はローカル変数にする必要はありません。
はい、さすがですね。笑
簡単にいうと、配列を描画する際にインスタンス変数ごと渡すとよしなにやってくれる!ということです。
この方法だと記述量も少なく、コレクション形式で値を管理しているということも明示的になるメリットもあります。注意点としては、コレクションでは、ローカル変数を渡しているので、ローカル変数で指定するようにしてください。
ちなみに下記を省略したものになります。使い勝手は上記の方がいいので、そちらだけは覚えましょう。
<%= render partial: "item", collection: @items %>
#partial -> view/_item.html.erbをレンダリング
#collection ->配列要素を回す書き方。省略もできる。
上記をさらに分解した形
<% @items.each do |item| %>
<%= render partial: "item", locals: { item: item } %>
<% end %>
newの場合
こちらも作成例から見ます。
<%= render 'form' %>
はい、こちらはnew
なのでイメージがつく人も多いと思います。
なぜならこのnew
アクションではインスタンスで値を管理していないからですね。(そもそもコントローラではインスタンス変数を作成しません。)
追記
ここまで、renderメソッドの使用方法をまとめました。
但し、あくまでも頻出の使い方をまとめたものです。これ以外にもController内で使用できる方法もあるので、そちらを知りたい方は下記の記事を参照してください。
【引用元】
【Rails 部分テンプレート(render partial)を用いたviewを別コントローラから呼び出す(render template)】
https://qiita.com/clbcl226/items/fe1b8e90b121332d1ca2
renderメソッドについて
https://qiita.com/ren0826jam/items/04bf2f0dc6dae08beb6a