ぴよログ

↓に移転したのでこっちは更新されません、多分。

Railsのrenderでdefined?による分岐

移転しました →

Railsrender partialでいろいろなViewが使いまわしているViewがあるとき。ある1つのViewのときだけ見た目をちょっと変えるってことをやろうとしたときに、defined?を使うと便利かもなーというお話。

前提

  • users/A.html.haml
  • users/B.html.haml
  • users/C.html.haml
  • users/D.html.haml
  • users/_shared.html.haml

上のようなテンプレがあって、A~Dの中身は擬似的に書くとそれぞれこんな感じになっているとする。要はsharedrenderしている。

-# A~D

%h1 A~C固有のタイトル
%div A~C固有の情報
= render partial: "shared"

_shared.html.hamlの中身はこんな感じで、Dのときだけは追加の情報を出したいとする。

%h1 共有部分
%div A~Dで共有

- if Dのときだけ
  %div D固有の情報

対処法

renderするときに引数のようなものをlocalsによって与えられるのでそれを使うのが楽そう。というわけで、A〜CとDでその内容を変えれば分岐はうまくいきそうだ。

-# A~C

%h1 A~C固有のタイトル
%div A~C固有の情報
= render partial: "shared", locals: { show_d: false }
-# D

%h1 D固有のタイトル
%div D固有の情報
= render partial: "shared", locals: { show_d: true }

上のようにshow_dとかいう変数を使ってあげれば、条件はこのように書くことができる。

- if show_d
  %div D固有の情報

もうちょっとよくする

上の方法だとDだけのためにA~C側にも変更が必要になって相当鬱陶しい。A~DのうちDだけに変更を加えて同じことを実現できるのが望ましいと思う。

やり方はA~Cにはlocalsは使わず、Dはlocals:{show_d:true}を。そして条件分岐のほうではdefined?を用いる。

- if defined? show_d
  %div D固有の情報

こうすると、Dの場合はshow_dがあるので実行され、A~Cの場合はshow_dなんて変数がないからこの条件は偽になって実行されない。renderする側の変更箇所が1箇所で済むからこっちのほうが良いと思う。

でもどことなくイケてないような感じはするんだよね。もっとRailsなやり方があったら知りたい。