验证Scoped加入的唯一性

时间:2016-12-29 16:30:37

标签: ruby-on-rails ruby

给出几张表:

products prices prices_regions regions

我想确保某个地区和产品的价格是唯一的。是否可以使用validates_uniqueness_of来编写它,还是需要自定义验证?

例如:

laptop = Product.create(name: "Laptop")
tablet = Product.create(name: "Tablet")
brazil = Region.create(name: "Brazil")
canada = Region.create(name: "Canada")
mexico = Region.create(name: "Mexico")
Price.create(product: laptop, regions: [brazil, mexico])
Price.new(product: laptop, regions: [canada]).valid? # true
Price.new(product: laptop, regions: [canada, brazil]).valid? # false
Price.new(product: laptop, regions: [canada, mexico]).valid? # false
Price.new(product: laptop, regions: [brazil, mexico]).valid? # false
Price.new(product: tablet, regions: [brazil, mexico]).valid? # true

1 个答案:

答案 0 :(得分:0)

我发现自定义验证器非常适合这样的逻辑,你可以根据需要使它们变得简单或复杂,并且以后很容易扩展逻辑。在这种情况下,它看起来像这样:

# app/models/price.rb
class Price < ActiveRecord::Base
  validates :regions, regions: true
  #...
end


# app/validators/regions_validator.rb
class RegionsValidator < ActiveModel::EachValidator

  def validate_each(price, _attribute, regions)
    if price_exists?(price, regions)
      price.errors.add(:regions, :uniqueness, message: 'must be unique')
    end
  end

  def price_exists?(price, regions)
    Price.where(product: price.product, regions: regions).present?
  end
end

修改

抱歉,要明确回答问题 - 您需要一个自定义验证器。 validates_uniqueness_of仅验证相关表格的列(即Price)。