scopeオプション
RailsのActiveRecord::Base.validates_uniqueness_ofは次のような使い方ができる。
class Comment validates_uniqueness_of :blog_id, :scope => :user_id
これは、commentsデーブルに、同一のuser_idに対するblog_idは一意である。という制約を持たせている。
scopeオプションを使用する際の注意
この場合、以下のようなコードを書いては行けない。
class Blog < ActiveRecord::Base has_many :comments def add_comment(comment, commenter) comment = Comment.new(:content => comment, :user_id => commenter.id) if comment.valid? self.comments << comment end end end
まずいのは、valid?のタイミング。この時は、commentオブジェクトは、どのblogと関連付けられるのかを知らないので、userは同一のblogに対しては1つしかコメントできないという制約の検証が正常に行われない。
この場合は、「self.comments << comment」がfalseになる。valid?した後にfalseというのはあまり良くない。
よって、次のように書きます。
def add_comment(comment, commenter) comment = Comment.new(:content => comment, :user_id => commenter.id, :blog_id => self.id) if comment.valid? self.comments << comment end end
これによって、valid?を呼ぶ際に、commentオブジェクトは、user_idとblog_idの両方を知っているので、validates_uniqueness_ofの検証が正常に行われる。