お使いのブラウザはサポート対象外です。

2022年06月02日(木) の日報

2

クエリを節約するとインタフェースの一貫性が壊れる

RailsのバリデーションとDBの制約が重複しているケースがあるので、DBの制約に寄せるとクエリが節約されて良いんじゃん?と個人的に思っている。すでにそれを実現しているgemもある。が、よくよく考えると公式でそれをやるの結構むずいよなーとなったのでそれをなぐり書きしておく。

class Post < ApplicationRecord
  belongs_to :user
  validates :title, length: {maximum: 10}
end

のようなPostがあるとき

post = Post.new(user_id: 0, title: 'a' * 11)
post.valid?

とすると当然userがない、というのとタイトルが長い、というバリデーションエラーになる。が、belongs_toによるバリデーションをDB側に寄せるとvalid?のタイミングではそれを検知することができないのでタイトルが長い、というエラーだけになってしまう。

という問題があるのでいまクエリを投げてuserが存在するかを毎回チェックする仕様になっているのだと思う。が、まあuser_id: 0なんて指定することはないのでバリデーションの一貫性は崩してもいいんです、というケースはそれなりにあるはずなのでユースケースによって選択できると一番いいのかもしれないなー