概要
以下みたいなコードを見ると思う。4件だからいいが10件とかあったり、ネストが深いと悲しくなってくる。
どうにか簡単に、繰り返しを少なく書きたい。ついいろいろ試してしまう。
<ul>
<li>
<div>ユーザ名</div>
<div><%= user.name %></div>
</li>
<li>
<div>メールアドレス</div>
<div><%= user.email %></div>
</li>
<li>
<div>性別</div>
<div><%= user.sex == 1 ? '男性' : '女性' %></div>
</li>
<li>
<div>役割</div>
<div><%= user.role %></div>
</li>
</ul>
1. 単純な繰り返しの場合
DraperとActive Recordモデルの翻訳を使うと以下のようにかける。
単純な繰り返しで良ければこれで大丈夫
<!-- sex_textメソッドをUserDecoratorに追加すること。 -->
<ul>
<% %i[name email sex_text role].each do |key| %>
<li>
<div><%= User.human_attribute_name(key) %></div>
<div><%= user.send(key) %></div>
</li>
<% end %>
</ul>
2. 部分的な繰り返しの場合
途中にモデル外のものが混ざってしまう場合、単純なループではだめになる。3回以上同じ記述が現れてしまうが、以下のようにすれば少しは減らせる
<ul>
<% %i[name email].each do |key| %>
<li>
<div><%= User.human_attribute_name(key) %></div>
<div><%= user.send(key) %></div>
</li>
<% end %>
<!-- 途中に今日の天気を入れる指示が来た -->
<li>
<div>今日の天気</div>
<div><%= Wheather.today %></div>
</li>
<% %i[sex_text role].each do |key| %>
<li>
<div><%= User.human_attribute_name(key) %></div>
<div><%= user.send(key) %></div>
</li>
<% end %>
</ul>
3. Helperを使う
htmlの記述を3回繰り返すのは嫌なので、せめてメソッドにする。
class UsersHelper
def user_param_li(label, value)
tag.li do
tag.div(label) +
tag.div(value)
end
end
end
<ul>
<% %i[name email].each do |key| %>
<%= user_param_li(User.human_attribute_name(key), user.send(key)) %>
<% end %>
<!-- 途中に今日の天気を入れる -->
<%= user_param_li('今日の天気', Wheather.today) %>
<% %i[sex_text role].each do |key| %>
<%= user_param_li(User.human_attribute_name(key), user.send(key)) %>
<% end %>
</ul>
4. クラスを用意してしまう
やっぱり読みづらいし、繰り返し構造が見えないので悲しい。オブジェクトを用意してしまう。
# このオブジェクトは、「サービスオブジェクト」「Presenter」「view_object」「PORO」など様々な呼ばれ方をされます。
# この役割なら、僕はプレゼンターという名前をつけると思います。
class UserParamsPresenter
attr_reader :user
def initialize(user)
@user = user
end
def params
[
user_param(:name),
user_param(:email),
wheather_param,
user_param(:sex_text),
user_param(:role),
]
end
private
def wheather_param
['今日の天気', Wheather.today]
end
def user_param(key)
[User.human_attribute_name(key), user.send(key)]
end
end
<ul>
<!-- このPresenterはcontrollerからも渡せます。僕はどっちがいいのかわかりません -->
<% UserParamsPresenter.new(user).params.each do |label, value| %>
<%= user_param_li(label, value) %>
<% end %>
</ul>
5. やりすぎたので反省してViewだけで見てもわかりやすく書く
このケースではこんなに複雑にする必要はなかったかもしれない。デザイナーが困る。
ちょっとならrubyのコードをerbに書いちゃってもいいよね?Presenterは消せる。
<%
user_params = [
[User.human_attribute_name(:name), user.name)],
[User.human_attribute_name(:email), user.email)],
['今日の天気', Wheather.today],
[User.human_attribute_name(:sex_text), user.sex_text)],
[User.human_attribute_name(:role), user.role)],
]
%>
<ul>
<% user_params.each do |label, value| %>
<%= user_param_li(label, value) %>
<% end %>
</ul>
6. ここだけであればそもそももっと簡単にかけそうだ
HelperやらDraper,I18nなんてついやってしまったが、別にそれもなくてもそこそこきれいに書けるのでは?
急ぎのプロジェクトだしなあ。
<%
user_params = [
['ユーザ名', user.name],
['メールアドレス', user.email],
['今日の天気', Wheather.today],
['性別', user.sex == 1 ? '男性' : '女性'],
['役割', user.role],
]
%>
<ul>
<% user_params.each do |label, value| %>
<li>
<div><%= label %></div>
<div><%= value %></div>
</li>
<% end %>
</ul>
まとめ
という感じで、いくつも書き方は思い浮かんでしまい、逡巡することになります。
この内、どれがいいかは場況を見るしかありません。
自分ではあまり書いたことのない書き方があれば、まずはぜひ手を動かして書いてみてください。
とりあえず書いてみて、数週間後の仕様変更や、同僚からのコメントで書き方が適切だったかどうかが試されます。