has_many :throughによる関連と一意性制約

has_many :throughで多対多の関連を設定する場合に、組み合わせの一意性を検証する方法。Railsレシピブックにあった例ですが、EntryとCategoryの間に多対多の関連があり、それをCategorizationsとしている場合に一意性を検証するには、

class Categorizations < ActiveRecord::Base
  belongs_to :category, :dependent => :destroy
  belongs_to :entry, :dependent => :destroy

  # ここを追加
  validates_uniqueness_of :category_id, :scope => [:entry_id]
end

class Category < ActiveRecord::Base
  has_many :categorizations

  # Categorizationsを通じて、Categoryを取得する
  has_many :categories, :through => :categorizations
end


class Blog < ActiveRecord::Base
  has_many :categorizations

  # Categorizationsを通じて、Entryを取得する
  has_many :entries, :through => :categorizations
end

の様に、Categorizationsにvalidates_uniqueness_ofを追加するとよいようです。これで、Entryに重複したCategoryを追加しようとすると、

>> entry.categories << category  # すでに登録されているCategory
ActiveRecord::RecordInvalid: Validation failed: Category has already been taken
...

というエラーが発生します。