はじめに
パーシャルの内容がほとんどおなじで、一部だけ表示を変えたい(追加したい、非表示にしたい)要件がでてきました。
たとえば、以下のようなときです。
-
posts#index
:「タイトル、公開日、書いた人」が確認できる -
users#show
:ユーザーの記事一覧が「タイトル、公開日」で確認できる。けれど「書いた人」の列は表示させない
画面のイメージ
posts#index
では、すべての列が表示されて、
タイトル | 公開日 | 書いた人 |
---|---|---|
タイトル | 公開日 | 書いた人 |
users#show
では、「書いた人」の列が表示されません。
タイトル | 公開日 |
---|---|
タイトル | 公開日 |
解決策1:defined?
で条件分岐させる方法
Railsのrenderでdefined?による分岐 - PIYO - Tech & Life -で紹介されていた「defined?
をつかった分岐」をするとスッキリと意図どおりに書くことができて便利でした。
index.html.haml
= render "posts/list", posts: @user.posts
with_name_column: true
show.html.haml
= render "posts/list", posts: @user.posts
_list.html.haml
%table
%thead
%tr
%th タイトル
%th 公開日
- if defined? with_name_column
%th 書いた人
%tbody
- posts.each do |post|
%tr
%td= post.title
%td= l(post.created_at)
- if defined? with_name_column
%td= post.user.name
ですが、いくつか微妙なところがありました。
-
true
でもfalse
でも定義されていれば真になる(値に意味がなくてモヤッとする) -
if with_name_column
と書きたい(defined?
が冗長におもえる)
変数が定義されているかどうかを条件にするのでなく、ストレートにtrue, false
で判断したいです。
パーシャルの先頭にデフォルト値を設定すればスッキリした
_list.html.haml
-# 初期値をfalseにしておくと、"未定義"状態がなくなる!
- with_name_column ||= false
%table
%thead
%tr
%th タイトル
%th 公開日
-# 条件式もスッキリした!
- if with_name_column
%th 書いた人
%tbody
- posts.each do |post|
%tr
%td= post.title
%td= l(post.created_at)
- if with_name_column
%td= post.user.name
スイッチをONにするときは、上述したものとおなじようにwith_name_column: true
とすれば、意図した動作をします。なによりtrue
である意味が出ました。よいですね!
index.html.haml
= render "posts/list", posts: @user.posts
with_name_column: true
おわりに
「パーシャルは、呼び出し元から渡された値で動くもの」という考えが強かったため、「パーシャル内でデフォルト値を持っておく」という方法は発見でした
パーシャル先頭に初期値を設定していることで、コードを読んだときに「初期値があるということは、呼び出し側でスイッチさせる仕様がある」ということも伝わってよいなあと感じました。