はじめに
この記事では学習中に出会ったエラーとその解決までの道のりを自分のために記録しています。
初学者のため、理解が不十分なところがあるかもしれません。
その場合はご指摘いただけると幸いです。
起こった問題
パーシャルにローカル変数を渡そうとしたが上手くいかなかった
結論
localsオプションを使用してローカル変数を渡すときは
<%= render partial: ‘パーシャル名’, locals: { ローカル変数名: インスタンス変数名} %>
のpartialを省略せずに書く
またはpartialを省略するならlocalsも省略する
解決までの道のり
前提条件
- Solidusを使用してECサイトを作成中
- 商品カテゴリーページへのリンクを含むヘッダーをパーシャル化
なぜパーシャル内でインスタンス変数を使用しないほうがいいのか?
パーシャルとコントローラーが結びついてしまうと、コントローラー内の変数を変更したときにパーシャル内の記述も変更しなければならなくなり、せっかくパーシャルとして切り出したのに使い勝手が悪くなる…という理由だと理解しました。
(間違っていたらそっと教えてください)
ちなみにlocalsの説明に出てくる例は
<%= render partial: 'shared/header', locals: { user: @user } %>
このようにインスタンス変数名とローカル変数が同じだと思うのですが
<%= render partial: 'shared/header', locals: { person: @user } %>
このように別の名前にしても大丈夫でした。
当たり前ではありますが気になったもので…。でも試しにやってみてとても混乱したので使うことはなさそうです。
発生したエラー
元の記述はこんな感じです。
def set_categories
@clothing = Spree::Taxon.where(name: "clothing")
end
<%= render: 'layouts/header', locals: { clothing: @clothing } %>
<% if clothing.present? %>
<%= link_to clothing.name, category_path(clothing.id) %>
<% end %>
これで表示しようとするとこんなエラーが出ました。
ActionView:: Template: :Error (undefined local variable or method 'clothing' for #<ActionView:: Base: 0x0000000002ee50>
Did you mean? @clothing):
ローカル変数に値を渡せていない?
解決へ
冒頭にも書きましたが
<%= render partial: 'layouts/header', locals: { clothing: @clothing } %>
このようにrender partialと記述することで解決しました。
または、renderのままにするのであればlocalsも省略して下記のように書けます。
<%= render 'layouts/header', clothing: @clothing %>
感想
パーシャルを使うときは
<%= render ‘パーシャル名’ %>
と覚えていたので、localsオプションというのがあるんだな〜と思ってlocalsだけを追加してしまいエラーにハマりました。
ちゃんと解説を読めばわかることなのですが…。反省。