Railsの部分テンプレートからインスタンス変数を参照するのはやめよう。

Railsの部分テンプレートからインスタンス変数を参照するのはやめて、locals経由で渡された変数を参照しましょう、というお話。

前提

という内容のコントローラがあって、これからビューを実装にとりかかるところだとします。

  • ページ全体を描画するshow.html.erbというテンプレート
  • 見出しだけを描画する_header.html.erbという部分テンプレート(インスタンス変数@userに格納された値をテンプレート内から利用する)

という2種類のテンプレートを実装する場合、どんなふうにコードを書けばいいでしょうか。

僕が思う、悪いコードと良いコードを一つずつ紹介してみます。

悪いコード

良いコード

理由

悪いコードでは、部分テンプレートからインスタンス変数を直接参照しています。一方良いコードでは、部分テンプレートにlocals経由で渡された変数を参照しています。

悪いコードは、

  • テンプレート(show.html.erb)がインスタンス変数を参照していないので、テンプレートを描画するためにコントローラで何を用意すべきか明らかでない
  • 部分テンプレート(_header.html.erb)がインスタンス変数を介して、呼び出し元のテンプレートだけでなくコントローラとも結びついているので、再利用性が低い

のに対し、良いコードは

  • テンプレートがインスタンス変数を参照しているので、コントローラで用意すべきものが明らか
  • 部分テンプレートが呼び出し元のテンプレートとのみ関連しているので、再利用性が高い

です。

なんでこんな記事を書いたのかというと、お仕事中にこれに関連するバグが出たんですね。上に書いた悪いコードに似たコードがあり、さらにコントローラのテストコード(インスタンス変数の割り当てチェック)に漏れがあったという状況で、コントローラのアクションからインスタンス変数に値を割り当てるコードが削除されてしまったのです。チェックが甘かったのと、周りのコードが正直汚かったことも大きな原因ですが、コントローラで用意すべきものがViewで明らかになっていれば、コードの見通しも良くなってバグが発生する可能性も低くなったのかな、と思ったわけです。

とか書いていたら、「Rails Best Practices」で似たようなTipsが掲載されているのを発見しました

というわけでこれからは、部分テンプレートからインスタンス変数を参照するのはやめて、locals経由で渡された変数を参照するようにします。

ではでは。