ランキング機能を追加する際に、製品毎にレビューが多い順に並べる場合、下記内容でデータを取り出すことができる。
product_ids = Review.group(:product_id).order('count_product_id DESC').limit(5).count(:product_id).keys
@ranking = product_ids.map {|id| Product.find(id)}
reviewsカラム
id | review | product_id |
---|---|---|
1 | text | 3 |
2 | test | 1 |
3 | text | 1 |
4 | text | 3 |
5 | text | 3 |
6 | text | 2 |
product_id: 3>1>2の順にレビューが多い
productsカラム
id | name |
---|---|
1 | pen |
2 | glue |
3 | drill |
①モデル名.group(:カラム名)
groupはモデルメソッドとして元からあるため、:product_idなどでグルーピングする。
②limit(表示したい要素数)
①のままだと最終的にproduct_idの種類全てを取得してしまうため、ランキングに載せたい数を制限する
③order('count_カラム名 DESC')
count_カラム名またはcount(カラム名)でカラムの種類ごとにカウントして
descで多い順に並べる。(少ない順ならasc)
pry(main)> id = Review.group(:product_id).order('count_product_id DESC').limit(5).count(:product_id).keys
=> [3, 1, 2]
pry(main)> id = Review.group(:product_id).limit(5).count(:product_id).keys
=> [1, 2, 3]
# order('count_product_id DESC')をつけないと、product_idの1から順に取り出すだけになってしまう
④count
product_id毎のデータ数を配列形式で並べたハッシュを返すことができる。
{2=>10, 1=>4, 3=>1}
見方としては{product_idが2個=>データ数10個,,,という表示方法になる。
⑤keys
順にハッシュのキーを配列として取り出す。
⑤@ranking = map{|i| Product.find_by(product_id: i)}
map関数で配列の中を1つづつ取り出す。今product_idsの中にreviewが多い順にproduct_idが並んでいるため、find_byで各product_idのインスタンスを@rankingに代入する。