【Rails】複数のカラムを使ったユニーク制約の方法【uniqueness: scope】

rails

こんにちは。菜笑なえです。

Railsで一意であることのバリデーションにはuniqueness を使います。
今回は複数カラムを使ってユニーク制約をかける、uniquenessscope オプションについて解説していきます。

バリデーション例

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件しか作成できません。

おわりに

複数のカラムを使用してユニーク制約をかけるというのは、結構いろんな場面で必要になると思うので、ぜひ覚えておきたいオプションですね。

参考文献

ありがとうございます!

SNS

Twitter:@nae310_
Instagram:310nae