Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 6: UUIDで`first`や`last`を使う(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

Rails 6: UUIDでfirstlastを使う(翻訳)

UUIDを主キーに使うとさまざまなメリットを得られますが、Railsの「暗黙の順序」で問題が生じます。

2018年の記事ではfirstlastは名前付きスコープで使うことをおすすめしましたが、現在はもっと簡単に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のfirstlastヘルパーメソッドも利用できるようになります。

そうしない理由があるとすれば

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を検討してみてはどうかという意見も社内でありました。

参考: ソート可能なUUID互換のulidが便利そう - Qiita

ulid/spec - GitHub

関連記事

RailsのモデルIDにUUIDを使う(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。