使用关联范围的唯一性字段

时间:2015-11-19 18:49:20

标签: ruby-on-rails ruby-on-rails-4 activerecord rspec factory-bot

我想确保项目名称在组织中是唯一的。所以我使用了" validates_uniqueness_of:name,scope:[:organization]"在项目内。这不幸没有用。

错误(已编辑):

>   1) Item 
>      Failure/Error: @item_1 = create(:item, :item_category => @item_cat_1)
>      
>      NoMethodError:
>        undefined method `organization_id' for #<Item:0x00000002565840>

模型:

class Item < ActiveRecord::Base
  belongs_to :item_category
  has_one :organization, through: :item_category
  validates_uniqueness_of :name, scope: [:organization]
end

class ItemCategory < ActiveRecord::Base
    has_many :items
    belongs_to :organization
end

class Organization < ActiveRecord::Base
  has_many :item_categories
  has_many :items, :through => item_categories
end

理论上,正如我上面所做的那样,我可以使用item_category关联(belongs_to:item_category)作为organization_id吗?

如果以上情况不可能。我想我可以在item和item_category中有一个organization_id。但是,我们怎么能验证item.organization_id总是等于item_category.organization_id(它的关联)

1 个答案:

答案 0 :(得分:1)

  

可以不在项目中包含organization_id吗?

是的,不包含,因为列organization_id将是多余的。

对于复杂验证,我们通常使用自定义验证,这是我的示例,您可以更正它:

class Item < ActiveRecord::Base
  belongs_to :item_category
  has_one :organization, through: :item_category
  # validates_uniqueness_of :name, scope: [:organization]
  validate :check_uniqueness_of_name

  def check_uniqueness_of_name
    if Organization.includes(item_categories: :items).where.not(items: {id: self.id}).where(items: {name: self.name}).count > 0
      errors.add(:name, 'name was duplidated')
    end
  end
end