コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

RailsのViewPartialにて引数確認にdefine?を使うようなケースは本当にそこまでやるか立ち止まって考えて欲しい

人それぞれやり方はあると思うけど、自分はこう思うよ系雑記

環境

rails (5.2.0)

事例

前提の話

レイアウトとレンダリング | Rails ガイド の 「3.4.4 ローカル変数を渡す」にも紹介されているように部分Layoutには変数を渡すことができる。

▼contents/index.html.erb

<%= render :partial => "content", :locals => { title: @content.title , body:@content.body } %>

▼contents/_content.html

<p>タイトルは<%= title %>です</p>
<p><%= body %></p>

みたいな使い方をして locals => ハッシュ で渡すことができる。

問題例

上記の例に加えて、『bodyが設定されていない場合は「本文はありません」と表示したい』という要件が追加されたとする。イメージとしては以下

# 本文がない場合の呼び出し元
<%= render :partial => "content", :locals => { title: @content.title} %>

本文がないけどタイトルのレイアウトはそのまま流用したいという意識が働くと以下のようなコードができる。

▼contents/_content.html

<p>タイトルは<%= title %>です</p>
<% if defined?(body) do %>
  <p><%= body %></p>
<% else %>
  <p> 本文はありません </p>
<% end %>

問題点

この内容がつらいポイントとしては

  • 呼び出されるpartialが状態を気にして複数の振る舞いを持つ
  • 必須な変数、必須ではない変数ができてしまい、partial側で必須な変数を明文化しづらいので、使う側も必要な変数がわかりづらい

解決案

ここでは「DRYにしなくては…」という気持ちが強く働いたがためにpartialが複雑化しているとも考えられるので

  • 無理にDRYを意識してpartialを共通化しない
  • 変数が複数必要になってくるpartialはそれが使いやすいか立ち止まって考える

▼contents/_content.html

<p>タイトルは<%= title %>です</p>
<p><%= body %></p>

▼contents/_no_titlecontent.html

<p>タイトルは<%= title %>です</p>
<p>本文はありません</p>

ケースバイケースだけど、まとめられるからと無理くりまとめると辛くなるので、一度立ち止まって考えるのは必要だと思う。

関連リンク