Railsの技: cycleメソッドでビューのループの「i%2==0」を避ける(翻訳)
ビューのレンダリングで、ループの回数をトラッキングする必要が生じることがあります(1行ごとに背景色を変える「ストライプテーブル」を作る場合など)。
<!-- @foods = ["apple", "orange", "banana"] -->
<% @foods.each do |food| %>
<tr class="???">
<td><%= food %></td>
</tr>
<% end %>
皆さんも、CSSのodd
やeven
子セレクタ1を使うか、以下のようにRubyのeach_with_index
メソッドで背景色を切り替えてみたことがおありでしょう。
<% @foods.each_with_index do |food, i| %>
<tr class="<%= i % 2 == 0 ? 'bg-gray-200' : 'bg-gray-100' %>">
<td><%= food %></td>
</tr>
<% end %>
以下のようにi.odd?
やi.even?
で少々リファクタリングする手もあります。
<% @foods.each_with_index do |food, i| %>
<tr class="<%= i.even? ? 'bg-gray-200' : 'bg-gray-100' %>">
<td><%= food %></td>
</tr>
<% end %>
Railsには、こんなときに重宝するcycle
ヘルパーメソッドも用意されています。
使い方
cycle
ヘルパーは1個の配列を引数に取り、呼ばれるたびに配列の要素を順に返します。
上のコードは以下に置き換えられます。
<% @foods.each_with_index do |food, i| %>
<tr class="<%= cycle('bg-gray-200', 'bg-gray-100') %>">
<td><%= food %></td>
</tr>
<% end %>
cycle
ヘルパーにオプションを3つ以上渡すと、本当のありがたみが見えてきます。
<% @foods.each_with_index do |food, i| %>
<tr class="<%= cycle('bg-red-100', 'bg-orange-100', 'bg-yellow-100') %>">
<td><%= food %></td>
</tr>
<% end %>
cycle
を手動でリセットする必要がある場合や、コード間で共有する必要がある場合は、オプションにname:
キーを渡せます。
cycle("red", "white", "blue", name: "colors")
cycle("sm", "md", "lg", "xl", name: "sizes")
reset_cycle("colors")
reset_cycle("sizes")
cycle
では、to_s
に応答するオブジェクトなら何でも使えます。
<% @items.each do |item| %>
<div class="rotate-<%= cycle(0, 45, 90, 135, 180) %>">
<%= item %>
</div>
<% end %>
参考資料
- Rails APIドキュメント:
TextHelper#cycle
-
Tailwindドキュメント: 疑似クラスバリアント - Tailwind CSS
関連記事
概要
原著者の許諾を得て翻訳・公開いたします。