概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: ‘Fix’ first & last by explicitly setting implicit ordering - Andy Croll
- 原文公開日: 2020/03/01
- 著者: Andy Croll
日本語タイトルは内容に即したものにしました。
Rails 6: UUIDでfirst
やlast
を使う(翻訳)
UUIDを主キーに使うとさまざまなメリットを得られますが、Railsの「暗黙の順序」で問題が生じます。
2018年の記事ではfirst
やlast
は名前付きスコープで使うことをおすすめしましたが、現在はもっと簡単にActive Recordのデフォルトの振る舞いを再び有効にできるようになりました。
以下のように書くよりも
Active Recordモデル上のシーケンスでないid
に対して#first
や#last
を使うのを避ける。あるいはそれ用の特別な名前付きスコープを追加して使う。
以下のように書こう
モデルのimplicit_order_column
で、自動生成されたcreated_at
カラムを指定する。
class Coffee < ApplicationRecord
self.implicit_order_column = "created_at"
end
そうする理由
UUIDをデータベースで用いることで、「一意性」「代入可能性」「セキュリティ」という大きなメリットを得られます。
さらにそこに「self.implicit_order_column = "created_at"
」を1行足すことで、Railsのfirst
やlast
ヘルパーメソッドも利用できるようになります。
そうしない理由があるとすれば
implicit_order_column
はRails 6の機能です。それより前のRailsでは、以前の記事で説明したように明示的に順序指定を実装する必要があります。
明示的な順序指定のアプローチの方が、意図が明確になるので好ましいと思う人もいるでしょう。
データモデルでUUIDを使わないのであれば、この方法を使う理由はほぼありません。
ひとつ注意があります。2つのレコードの作成時刻が完全に一致すると、その2つのレコードの並び順は主キーの順序に従います。
もうひとつ注意すべきは、created_at
は(id
主キーと異なり)デフォルトではデータベースインデックスを持たないという点です。インデックスなしでこのクエリが走ると、データセットが巨大な場合に時間がかかる可能性があります。その場合はcreated_at
フィールドにデータベースインデックスを追加すべきです。
スペシャルサンクス
implicit_order_column
は、友人のTekinが思いついたアイデアがRailsに実装されたものです(#34480)。
Benjamin Alexanderからは、created_at
にデータベースインデックスが必要なことを指摘いただきました。
編集部追記(2020/10/15)
現在ならulidを検討してみてはどうかという意見も社内でありました。
created_atでimplicit_order_columnするのであれば、ULIDを使うという手もあるとは思う: Rails 6: UUIDで`first`や`last`を使う(翻訳) https://t.co/WfawnNQP6w
— Masato Mori (@morimorihoge) October 14, 2020
参考: ソート可能なUUID互換のulidが便利そう - Qiita