Rails验证has_many通过表的唯一性范围

时间:2014-03-22 09:16:07

标签: ruby-on-rails ruby-on-rails-3 validation associations unique

我为我的模型设置了has_many :through类型关联:

class Place < ActiveRecord::Base

  has_many :place_subcategory_relations, dependent: :destroy
  has_many :place_subcategories, through: :place_subcategory_relations, uniq: true

end


class PlaceSubcategory < ActiveRecord::Base

  has_many :place_subcategory_relations, dependent: :restrict
  has_many :places, through: :place_subcategory_relations, uniq: true

end

class PlaceSubcategoryRelation < ActiveRecord::Base

  belongs_to :place
  belongs_to :place_subcategory

  validates :is_primary, uniqueness: {scope: :place_id}

end

问题是,当我尝试将另一个子类别添加到某个地方时:

place.place_subcategories << PlaceSubcategory.find(84)

我收到此错误:

   (0.2ms)  BEGIN
  PlaceSubcategoryRelation Exists (0.6ms)  SELECT 1 AS one FROM "place_subcategory_relations" WHERE ("place_subcategory_relations"."is_primary" IS NULL AND "place_subcategory_relations"."place_id" = 169) LIMIT 1
   (0.2ms)  ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Is primary has already been taken

我还尝试先创建PlaceCategoryRelation,但没有提交任何内容:

p.place_subcategory_relations << PlaceSubcategoryRelation.new(place_id: p.id, place_subcategory_id: PlaceSubcategory.find(84).id)

   (0.2ms)  BEGIN
  PlaceSubcategoryRelation Exists (0.6ms)  SELECT 1 AS one FROM "place_subcategory_relations" WHERE ("place_subcategory_relations"."is_primary" IS NULL AND "place_subcategory_relations"."place_id" = 169) LIMIT 1
   (0.2ms)  COMMIT

我是否错误地使用了唯一性验证器?我无法弄清楚这里的问题是什么......

1 个答案:

答案 0 :(得分:1)

解决!

问题在于,因为is_primary是一个布尔值,所以它的假值也必须是唯一的,而不仅仅是真值。因此,当存在is_primary = false的另一个与is_primary = false的新关联时,它会失败,就像它应该的那样。

我通过使用它来验证它来解决它:

  validates :is_primary, uniqueness: {scope: :place_id}, if: ->{self.is_primary && self.class.where(place_id: self.place_id, is_primary: true).length > 0}

编辑:我想这也有效,而且更简单:

validates :is_primary, uniqueness: {scope: :place_id}, if: :is_primary