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
なんて指定することはないのでバリデーションの一貫性は崩してもいいんです、というケースはそれなりにあるはずなのでユースケースによって選択できると一番いいのかもしれないなー