パーシャルを使ってビューファイルを共通化する際にlocals
オプションを使うべきなのか分からなかったので調べてみました。
結論
パーシャルにはlocals
オプションを使ってローカル変数で値を渡した方が良い。
partialは呼び出し元のテンプレートとだけ紐づけておくようにしたほうがいい。 インスタンス変数を使うと、コントローラとも結びついてしまい、結果としてpartialとして切り出したのに再利用性が低くなる。
partialではインスタンス変数で値を渡すを参照しない方がいい - qiita
rails パーシャル(部分テンプレート)へローカル変数を渡したいとき - qiita
パーシャルでインスタンス変数を使わない方が良いと考える主な理由は「変数の影響範囲が広くなってしまう」ことのようです。具体的には次のようなことが考えられます。
- コントローラーの変更に伴ってパーシャルの変更も必要になってしまう
- モデルのデータへの依存度が高くなり柔軟性が無くなる
- パーシャルにローカル変数を使う事で再利用時に修正範囲が狭くて済む
パーシャルへの値の受け渡しはできるだけローカル変数を使った方が良さそうです。
注意点
パーシャルにローカル変数を使って値を渡す場合は次の2つに注意してください。
1. locals:
を明記する場合はpartial:
も一緒に明記する必要がある
locals:
を明記する場合はpartial:
も一緒に明記しなければエラー(undefined local variable or method
)が発生します。
locals:
はpartial:
と一緒に書くか、もしくは両方とも省略するのが正しい記述のようです。
# locals:を明記するにはpartial:の明記も必要 <%= render partial: "product", locals: { product: @product } %> # locals:を省略するならpartial:も省略すればok <%= render "product", product: @product %>
2. パーシャルからパーシャルへはローカル変数は引き継がれない
ローカル変数なのでパーシャルからパーシャルへ値を引き継ぐ(渡す)ことはできません。
パーシャルからパーシャルを呼び出す際にローカル変数の値を渡したい場合はobject
オプションを使うと良いようです。
locals
オプションと同様にローカル変数をパーシャルに渡すことができます。
また、as
オプションを併用するを使うことでローカル変数名を指定することも可能です。
# localsオプションでインスタンス変数@itemをローカル変数productとしてパーシャルに渡す <%= render partial: "product", locals: { product: @item } %> # objectオプションでインスタンス変数@itemをローカル変数itemとしてパーシャルに渡す <%= render partial: "product", object: @item %> # object + asオプションでインスタンス変数@itemをローカル変数名をitemに指定する(↑と同等) <%= render partial: "product", object: @item, as: "item" %>
実装例
app/views/users/index.html.erb
とapp/views/users/followers.html.erb
の共通項をapp/views/users/_list.html.erb
パーシャルを使って共通化したい。
# app/contollers/users_controller.rb def index @users = 全ユーザーの取得処理 end def followers @followers = フォロワーの取得処理 end
# app/views/users/index.html.erb <h1>Index</h1> # インスタンス変数@usersをローカル変数userでパーシャルに渡す <%= render partial: "list", locals: { users: @users } %>
# app/views/users/followers.html.erb <h1>Followers</h1> # インスタンス変数@followersをローカル変数userでパーシャルに渡す <%= render partial: "list", locals: { users: @followers } %>
# app/views/users/_list.html.erb # 渡ってきたローカル変数usersを使って表示部を共通化する <% users.each do |user| %> <%= user.email %> <%= user.name %> <%= link_to "#{user.nama}の詳細", user_path(user) %> <% end %>
まとめ
パーシャルへの値の渡し方とlocals
オプションの使い方が理解できたのでスッキリ。
FBCのRailsのプラクティスも残り少ないのでしっかり学んでいきたい。