1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Railsでテーブルの値を、別テーブルの項目で並び替える方法

Last updated at Posted at 2020-11-30

こんばんは
アロハな男、やすのりです!

今日は、Railsでモデルやテーブルを扱っていく上で1度は必ず通るであろうsort_byメソッドについて書いていこうと思います。
ただ普通に配列を並び替えわけではなく、今回はアソシエーションを組んでいる別テーブルの値で並び替えをする方法になります!!

#結論
並び替える方法が2種類あります。

  • 全く該当しない物は扱わない
モデル名.joins(:並び替えたい項目があるテーブル名).group(:まとめたい項目).order('count(並び替えたい項目)')
  • 該当しないものも扱いたい
テーブル情報を入れた変数.sort_by { |x| x.並び替えたい項目があるテーブル名 }

となります。

#テーブル構造
例えば以下の様なテーブルがあった場合で考えます。

  • experiencesテーブル(色んなお店やレジャー施設情報保存用)
  • usersテーブル(登録していただいているユーザー様の情報保存用)
  • favoritesテーブル(ユーザー様がお店等をお気に入りしたことを保存)

favoritesテーブルでは、他2つのidを外部キーとして持っています。
ユーザー様がお店やレジャー施設をお気に入り登録すると、

id user_id experience_id
1 1 1
2 1 3
3 2 1
4 3 2
5 2 2

こんな具合にテーブルに値が保存されていきます。

#なぜ2種類?
それでは、なぜ方法が2種類あるのかを見ていきたいと思います。

まず全く該当しない物は扱わない場合ですが、
こちらの重要部分はjoinsメソッドです。

詳しいことは↓こちらを見ていただく方がよりわかりやすいかと思います。
【Rails】joinsメソッドのテーブル結合からネストまでの解説書

簡単に説明すると、例えば

Experience.joins(:favorites)

とすると、experiencesテーブルとfavoritesテーブルの両方共に存在しているレコード情報しか検索できなくなってしまいます。

つまり、**お気に入り登録をまだされていないお店・レジャー施設は検索対象から外す。**ということになります。
検索対象から外さない場合の物は後述します。

続いて、

Experience.joins(:favorites).group(:experience_id).order('count(user_id) DESC')

と、記述することによりお気に入りされている数が多い順でお店等を取得することができます。

groupメソッドでexperience_idを指定することにより、複数お気に入り登録されているお店等を1つのレコードにまとめることができます。

そしてorderメソッドで並び替えをするんですが、メソッド内でcount(user_id)とすることによってお店等がお気に入り登録されている数で並び替えることができます。

ただこの方法ですと、お気に入り登録されている場所だけをピックアップして、そこから人気店を探す!!とかなら使用できるメソッドですが、**お店等を全て一覧で表示したいから除外されてしまうのは...**という場合もあると思います。

『それならjoinsメソッドを抜いてコードを書けばいいじゃん!!』

となりそうなんですが、その後のgroupメソッドではexperience_idを、countメソッドではuser_idを使用しています。
この2つのidはfavoritesテーブルが持っているテーブルですので、Experienceモデルだけでは使用できません...

その場合には、もう1種類の方法です。

#全て取得する方法
該当しないものも扱いたい場合ですが、こちらは先ほどまで説明していた方法とは少し違います。
具体的にはモデルではなくテーブルに対して並び替えをするということです。

1度変数等にレコード情報を格納してしまいます(今回は@experiencesとします。)

そして変数に対してsort_byメソッドを使用します。

@experiences.sort_by! { |exp| exp.favorites.length }.reverse!

と記述することで、全件のお店等を対象にお気に入り数が多い順で並び替えることができます。

sort_byメソッドを使用することで変数(配列)の並び替えをでき、{}内でその値を1つずつ取り出して評価していきます。

experiencesテーブルfavoritesテーブルはアソシエーションを組んでますので、

exp.favorites.length

と記述することで、1つずつ取り出してきたお店のお気に入り数を評価して並び替えをしてくれます。
ただこのままだと昇順での並び替えになってしまいますので、最後にreverseメソッドで結果を反転させています。

#最後に
最初は全部モデルに対してだけで並び替えができると思い込んでいたので、すごく時間がかかってしまいました...

いや、もしかしたらこれ以外にもっといい方法があるかも...?

ご指摘・アドバイスはどんどんいただきたいと思っていますので、コメントお待ちしています!!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?