2016-12-29 3 views
1

Учитывая несколько таблиц:Validate Уникальность контекстного Присоединиться

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 

ответ

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 

EDIT

К сожалению, на самом деле ответить на этот вопрос явно - вам нужен собственный валидатор. validates_uniqueness_of проверяет только столбцы таблицы (то есть Price).

+0

Для простой проверки «уникальной внутри области видимости» это [встроенный в валидаторы Rails] (http://guides.rubyonrails.org/active_record_validations.html#uniqueness) - вы можете сделать что-то вроде: ' проверяет: цена, уникальность: {scope:: region} '. Однако, поскольку в этом случае мы имеем дело с таблицей соединений и более сложной логикой, я согласен с тем, что то, что вы описали выше, является лучшим. –

Смежные вопросы