3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Rails5でID順にorder byしたい時にActiveRecord::IrreversibleOrderErrorが発生することがある

TL;DR

  • ActiveRecordFIELD関数を使っているときにreverseをすると、ActiveRecord::IrreversibleOrderErrorが発生します。
  • 今回は、 order_as_specified gemを使ってこの問題を回避しました。

GitHub - panorama-ed/order_as_specified: Add arbitrary ordering to ActiveRecord queries.

起こったこと

タイムラインとかフィードを持つコンテンツや、ランキングなどの順番を別のロジックで生成している場合などに、指定したID順でレコードを取得したいケースがあると思います。

MySQLであれば、 FIELD関数が使えますし、Rails5を使っていれば下記のように記述できます。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5 文字列関数

ids = something_ordered_ids
Content.order(['field(`contents`.`id`, ?)', ids])

これと併用して、 reverseを使ってしまうと、ActiveRecord::IrreversibleOrderErrorが発生します。

単純にreverse できないようなクエリを実行しようとすると、 ActiveRecord::IrreversibleOrderErrorthrow します。ちなみに、last などと併用しても内部的にはreverseを使っているので、この例外がthrowされます。
rails commit log流し読み(2016/01/28) - なるようになるブログ

上記コードで生成されるクエリは、下記のようになっているので単純にreverseができないようです。

SELECT `contents`.* FROM `contents` WHERE `contents`.`id` IN (9, 8, 3, 4, 2, 1) ORDER BY field(`contents`.`id`, 9,8,3,4,2,1)

どうしたか

order_as_specifiedgemを使って回避しました。

ruby - rails のwhere句の結果を指定の順番で取り出す方法は? - スタック・オーバーフロー
GitHub - panorama-ed/order_as_specified: Add arbitrary ordering to ActiveRecord queries.

order_as_specified gemを使うと、FIELD関数ではないアプローチでID順に並べようとします。

SELECT `contents`.* FROM `contents` ORDER BY `contents`.`id`=9 DESC, `contents`.`id`=8 DESC, `contents`.`id`=3 DESC, `contents`.`id`=4 DESC, `contents`.`id`=
2 DESC, `contents`.`id`=1 DESC 

このクエリであれば、単純にreverseできるクエリを発行することができるので、 例外が発生しなくなりました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
3
Help us understand the problem. What are the problem?