はじめに
ブランド情報を管理するBrandモデル&実際のデーターが以下のような状況の時にアルファベットごとにグループ化する方法がすぐにわからなかったのでメモっておきます
app/models/brand.rb
# == Schema Information
#
# Table name: brands
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class Brand < ActiveRecord::Base
end
{ "name": "titivate"},
{ "name": "MERCURYDUO"},
{ "name": "GYDA"},
{ "name": "jouetie"},
{ "name": "PAMEO POSE"},
{ "name": "MURUA"},
{ "name": "dazzlin"},
{ "name": "merry jenny"},
{ "name": "Re:EDIT"},
{ "name": "Agneau7"},
{ "name": "ANAP"},
{ "name": "Apuweiser-riche"},
{ "name": "AULA AILA"},
{ "name": "BACKS"},
{ "name": "Boisson Chocolat"},
{ "name": "BONICA DOT"},
{ "name": "bpb"},
{ "name": "BUBBLES"},
{ "name": "Candy Stripper"},
{ "name": "X-girl"},
{ "name": "UNRELISH"},
{ "name": "deicy"},
{ "name": "chuu"}
最初に考えた書き方
こんなのを思いつきました。
mapが2回出てくる時点でちょっと気持ち悪いし、これだと後でメンテナンスするのはちょっとツライなぁと思ってました
@brands = Brand.all
brands_group_by_alphabet = ("A".."Z").map do |alp|
{
alphabet: alp ,
brands: @brands.select{|brand| brand.name[0] == alp}.map{|brand| brand}}
end
もっとスッキリ書ける
ActiveRecordでgroup Byしてカウントをして、カウント数でorderするを読んで、group Byできることを知りました。
この記事で突破口が開けた感じがしたものの、アルファベットごとにどのようにグループ化すればいいのかすぐにわからなかったのですがRubyリファレンス見て以下のようにすることで意図したことができました。
Brand.all.group_by {|brand| brand.name.chr.upcase }.sort
=> [["A",
[#<Brand:0x007fc42fed8398
id: 11,
name: "Agneau7",
#<Brand:0x007fc42fed8230
id: 12,
name: "ANAP",
#<Brand:0x007fc42fed80c8
id: 13,
name: "Apuweiser-riche",]],
["U",
[#<Brand:0x007fc430abb3b8
id: 22,
name: "UNRELISH"]],
["X",
[#<Brand:0x007fc430abb520
id: 21,
name: "X-girl",
>]]]
少し補足すると
- chrで文字列の最初の1文字を新しい文字列で返してあげる
- ブランドは大文字と小文字が混在してるのでひとまず大文字で統一
することでアルファベットごとにグループ出来ます。