Rails uniquenss 複数カラムのとき(nilともできる)

以下のようなモデルがあるとする。

class CreateAccessPermission < ActiveRecord::Migration
  def change
    create_table :project_expirations do |t|
      t.reference :user
      t.datetime :expired_at

      t.timestamps
    end
  end
end

このモデルは、あるユーザに対してアクセスパーミッションを発行する時に使われる。
このパーミッション自体は expired_atに値が入っていない場合に有効。
レコードが作成された段階では expired_atに値はない。

validation

ユーザに、有効なアクセス権を重複して付与しないようにしたい。
そこで、以下のような validationを書いていた。

class AccessPermission
  validate :not_duplicate_permission

  def not_duplicate_permission
    self.where(user_id: user_id).where.not(expired_at: nil).exist?
  end
end

けど、以下のようにかけることを知った。
(なぜか nilとの掛け合わせで uniquenessを検証することは出来ないと思いこんでいた。)

class AccessPermission
  validates :uniqueness, :user_id, { scope::expired_at }
end

より簡潔に

さらにこんなふうなメソッドがあることを知った

class AccessPermission
  validates_uniqueness_of :user_id, scope: expired_at
end

さらにさらにより多くのカラムとの組み合わせも実現できる。
(今回のモデルの場合は必要ないけど、)

class SampleModel
  validates_uniqueness_of :user_id, scope: [:expired_at, :email]
end

さらに組み合わせ時の条件も指定できる

class SampleModel
  validates_uniqueness_of :email, conditions: -> { where.not(deleted_at: nil) }
end

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です