ActiveRecordでkakurenbo-putiを使っている時のuniqueness検証


  • Padrinoアプリを作っているうちに、モデルのuniquenessの検証をする必要があった。モデルには論理削除を設けているので、論理削除されたものは除外してuniquenessの検証をする必要があった。
  • かつてparanoiaを使っている時は、validates_as_paranoidとしておくと適切に処理してくれたが、paranoiaはActiveRecordのバージョンアップに伴って動かなくなることがあって辛かった。
  • ActiveRecordのメソッドを上書きしないkakurenbo-putiを使うようにしているが、uniqueness検証の書き方で錯誤したので、記す。
  • 最初こう書いた。
models/a.rb
class A < ActiveRecord::Base
  soft_deletable column: :deleted_at
  validates :name,
            uniqueness: {unless: :soft_destroyed?, message: "This name in Japanese is already existing."}
end

こうすると、A.new(name: "あ")した時には当然soft_destroyed?nilなのですり抜けてしまう。

  • こう書くのが正しいと思う。
models/a.rb
class A < ActiveRecord::Base
  soft_deletable column: :deleted_at
  validates :name,
            uniqueness: {conditions: ->{without_soft_destroyed}, message: "This name in Japanese is already existing."}
end
  • uniqueness検証の場合、今から作成や格納しようとするレコードを見て足りるわけではなく、あるスコープ全体を見る必要があるということに気付いた。