こんにちは。菜笑なえです。
Railsで一意であることのバリデーションにはuniqueness
を使います。
今回は複数カラムを使ってユニーク制約をかける、uniqueness
のscope
オプションについて解説していきます。
目次
バリデーション例
class Like < ActiveRecord::Base
validates :tweet_id, uniqueness: { scope: :user_id }
end
今回はTwitterを例に考えています。
Twitterのユーザーは、「1ツイート」に対して「1いいね」しかすることができないため、このようなバリデーションになります。
uniqueness: scope を使ったユニーク制約方法の解説
上記はいいねを保存するLike
モデルのtweet_id
カラムに対するバリデーションです。
もしscope
を付けずに以下のようにしたらどうでしょうか?
class Like < ActiveRecord::Base
validates :tweet_id, uniqueness: true
end
これだと「1ツイート」に対して「1いいね」しか付けることができません。
早い者勝ちで、一番最初に誰かがいいねをしたら、それ以上そのツイートにはいいねが付けれなくなります。
それでは、Twitterは成り立ちませんね。
そこでscope
の登場です。
scope
は範囲を指定して、一意かどうかをチェックしてくれます。
今回だとuser_id
で範囲を限定しています。
class Like < ActiveRecord::Base
validates :tweet_id, uniqueness: { scope: :user_id }
end
これで「1ユーザー」が「1ツイート」に対して「1いいね」という範囲を限定した一意チェックを実現できます。
scope は複数指定OK
scope
は配列にして複数指定できます。
validates :tweet_id, uniqueness: { scope: [:group_id, :user_id] }
これでtweet_id
, group_id
, user_id
の全てが同じデータは1件しか作成できません。
おわりに
複数のカラムを使用してユニーク制約をかけるというのは、結構いろんな場面で必要になると思うので、ぜひ覚えておきたいオプションですね。
参考文献
ありがとうございます!