0
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?

はじめに

こんにちは、HappyManaです。
Railsで並び替えをしたいときに使うgemで、大きくacts_at_listranked-modelがあります。
この2つのgemの違いがわかりにくかったため、紹介するとともに違いを書いていきます。

並び替え用のdbカラムは、row_orderカラムとします。

dbに入る値が異なる

最も異なるのがこれです。
他にもいろいろ違いはありますが、1番大きな違いなので、これを説明していきます。

acts_as_list

acts_as_listでは、カラムに1、2など「そのレコードが何番目か」が入っています。
例えば、現在3番目のレコードを2番目に並べ替えたいとき、acts_as_listでは、2番目と3番目のレコードのrow_orderカラムが変更されます。

id row_order
1 1
2 2
3 3

id row_order
1 1
2 3
3 2

そのため、並べ替えたい先の番号より後の番号のレコードはすべて更新されます。

値の更新では、対象のレコードと、それ以外の変更する必要のあるレコードをwhereで絞り込んで+1もしくは-1するというUPDATE文になるので、クエリ数は2回で済むようになります。
今回の例では、id=2と3の2レコードしかありませんが、100行になっても2回で済みます。

ただし、デメリットとして、3レコードしかない状況で、「100」などの最後尾の番号より大きい値を入れると、最後尾の番号ではなく、100番という絶対的な値が入るというデメリットがあります。

ranked-model

一方で、ranked-modelは、カラムに-1073741823、126322567など「そのレコードの重み」が入っています。

これをすると、重みが軽い順に並びます。
これによって、「1レコードを並び替えた時に、そのレコードのみUPDATEされる」という処理になります。

例えば、現在3番目のレコードを2番目に並べ替えたいとき、ranked-modelでは、1番目と2番目のrow_orderカラムの値の合計/2の値が3番目のレコードのrow_orderカラムに入ります。

id row_order
1 100
2 200
3 300

id row_order
1 100
2 200
3 150

そのため、対象のレコードのみUPDATEされます。

ただし、1番目と2番目のrow_orderカラムの値にすき間がない場合、重みが振り分けられます。
そうなると、すべてのレコードのrow_orderカラムの値が変わるため、クエリ数がN+1になります。

まあINTEGER型なので、-2147483647~2147483647の間で均等に割り振られるため、頻繁にN+1は起きないと考えられます。

デメリットとしては、上で挙げた重みを振り分ける際にクエリ数がN+1になる可能性があるということ、またすべてのレコードを確認しないとそのレコードが何番目かわからないということがあります。

おわりに

acts_as_listとranked-modelの違いを書きました。
それぞれで処理の内容が違って興味深かったです。
個人的には、関係ないレコードはUPDATEされないranked-modelの方が好みではあるのですが、2クエリでまとめてUPDATEするacts_as_listも魅力的ではあるなと思いました。

0
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
0
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?