Rails4

特定のカラムの初めの頭文字でグループ化する方法

More than 3 years have passed since last update.

はじめに

ブランド情報を管理する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",
    >]]]

少し補足すると

することでアルファベットごとにグループ出来ます。