2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RailsのViewでの微妙に異なる繰り返しの書き方をいくつか

Last updated at Posted at 2020-05-29

概要

以下みたいなコードを見ると思う。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. 単純な繰り返しの場合

DraperActive 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>

まとめ

という感じで、いくつも書き方は思い浮かんでしまい、逡巡することになります。
この内、どれがいいかは場況を見るしかありません。
自分ではあまり書いたことのない書き方があれば、まずはぜひ手を動かして書いてみてください。
とりあえず書いてみて、数週間後の仕様変更や、同僚からのコメントで書き方が適切だったかどうかが試されます。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?