【Rails】whereで指定したIDなどの順番で記事を取得する方法

RailsでActive Recordを利用して記事を取得した場合、whereに指定したIDなどの順番通りにデータを取得したいときはありますよね。

ただし、デフォルトではwhereに入れる順番を調整したとしても、取得時にはソートされ直してしまいます。

例えば、下記のように複数のIDを指定したとします。

Model.where(id: [3,4,1,2])

その結果、取得されるデータはIDが若い順(1, 2, 3, 4)となってしまいます
もちろんorderを使ってうまく調整できればいいのですが、難しいときもあるはず。

小難しいことはせずwhereに入れた順番でそのまま取得したいときは、ちょっと工夫が必要なのでその方法をまとめました。

実行環境:
Rails 6.1.4
Ruby 2.7.4

目次

whereで指定した順番で取得する方法2つ

主な方法は下記の通り2つあります。

  • FIELD関数を使う
  • gem「order_as_specified」を使う

FIELD関数を使う

Model.where(id: ids).order(['field(id, ?)', ids])

Ruby v4.2.5以降から使えるようになったものです。
利用自体はシンプルで、MySQLでもPostgreSQLでも動作します。

ただし、私の場合は本番環境で一部うまく動作しなかったので、次に紹介するgemを使う方法を採用しました。

gem「order_as_specified」を使う

whereで指定した順でデータが取得できるようにしてくれる便利なgemが「order_as_specified」。

https://github.com/panorama-ed/order_as_specified

使い方も非常に簡単です。

1. gemを追加する

まずGemfileに以下のように記述します。

gem 'order_as_specified'

その後bundleでインストール。

$ bundle install

これでgem「order_as_specified」の追加が完了です。

2. Modelにて設定

使いたいModelで下記のようにextendを使って読み込みます。

class Model
  extend OrderAsSpecified
end

3. whereを使うときに追記する

使うときは、whereに続いて取得順を定義すればOK。

whereでID指定で記事を取ったあと、そのIDの順番でソートしたい場合は下記の通りとなります。

id_array = [3,4,1,2]
Model.where(id: id_array).order_as_specified(id: id_array)

もちろん、limitなどをつなげることも可能です。

id_array = [3,4,1,2]
Model.where(id: id_array).order_as_specified(id: id_array).limit(5)

https://stackoverflow.com/questions/8505079/activerecord-order-by-external-array/29039262#29039262

具体的には、下記のようにorder句を生成してくれているようです。

ORDER BY ID='3' DESC, ID='4' DESC, ID='1' DESC, ID='2' DESC

まとめ

あらかじめwhereにて取得したい順にしておいても、Railsでは関係なくソートされてしまいます。

やはり何らかの理由があって「この順番がよい」というときには重宝する方法ではないでしょうか。

ぜひgem「order_as_specified」も使ってみてくださいね!

この記事が気に入ったら
いいね または フォローしてね!

SHARE

コメント

コメントする

目次
閉じる