データベースのタイトルのリストをアルファベット順およびブロック単位で表示しようとしています。
私は手紙を出力し、その手紙で始まるすべてのタイトルを含めたいと思っています。例えば:
- あ
- アップル
- 別物
- B
- ボブ
.order('title') を使用して結果を並べ替えることができることはわかっていますが、表示コードを記述する最良の方法がわかりません。
データベースのタイトルのリストをアルファベット順およびブロック単位で表示しようとしています。
私は手紙を出力し、その手紙で始まるすべてのタイトルを含めたいと思っています。例えば:
.order('title') を使用して結果を並べ替えることができることはわかっていますが、表示コードを記述する最良の方法がわかりません。
titles.group_by {|word| word[0].upcase }
したがって、次の場合:
titles = ['Apple', 'anothersomething', 'Bob']
それで:
grouped_titles = titles.group_by {|word| word[0].upcase }
=> {"A"=>["Apple", "anothersomething"], "B"=>["Bob"]}
順序を確認するために、結果のハッシュを並べ替えて、配列に変換することができます。
grouped_titles = grouped_titles.sort_by{|k, v| k}
=> [["A", ["Apple", "anothersomething"]], ["B", ["Bob"]]]
次に、結果の配列を反復処理できます。
<% grouped_titles.each do |initial_letter, titles| %>
-display stuff here-
<% end %>
これはデータベースではなくRubyでグループ化されていることに注意してください(.group
リレーションのメソッドを使用して実行されます)が、ページにすべてのデータを既に表示している場合は、このメソッドで問題ありません。
@MrTheWalrusによって提案された解決策は、順序を維持するためにリストを適切に反復する限り機能すると思いますが、リストが長くなった場合に少し速くなる代替案を提案します。まず、リストが正しいように表示されていることを確認します。
@titles = Title.order(:title)
次に、ビューの反復は次のようになります。
<% cur_letter = nil %>
<% @titles.each do |t| %>
<% title_letter = t.name[0].capitalize.match(/[A-Z]/) ? t.name[0].capitalize : "#" %>
<% if title_letter != cur_letter %>
<% cur_letter = title_letter %>
<%= cur_letter %>
<% end %>
<%= t.name %>
<% end %>
ビューコードとしては少し醜いことは認めますが、リストを1回繰り返して順序を維持しgroup_by
、簡単な操作ではないことを回避できます。