我有以下型号:
class Property < ActiveRecord::Base
belongs_to :property_type
has_many :variant_properties
has_many :variants, through: :variant_properties
end
class PropertyType < ActiveRecord::Base
has_many :properties
end
class Variant < ActiveRecord::Base
has_many :variant_properties
has_many :properties, through: :variant_properties
end
class VariantProperty < ActiveRecord::Base
belongs_to :property
belongs_to :variant
validates_uniqueness_of :property, scope: :property_type
end
我要验证的是,同一Variant的两个属性永远不应属于同一个Property_Type。
有没有办法以 Rails 方式执行此验证?
编辑:
最后使用自定义验证器解决,如@ qaisar-nadeem所示。冗余列也可以,但我认为它不仅仅是一个优化解决方案。
class Property < ActiveRecord::Base
(...)
validate :property_type_uniqueness
private
def property_type_uniqueness
unless property_type_unique?
msg = 'You cannot have multiple property variants with same property type'
errors.add(:property_id, msg)
end
end
def property_type_unique?
VariantProperty
.where(variant: variant)
.select { |vp| vp.property.property_type == property.property_type }
.empty?
end
end
答案 0 :(得分:1)
验证scope
无法访问已连接的表,因此您需要进行自定义验证。
所以有两种选择。
选项1:使用自定义验证器并使用SQL检查是否存在具有相同属性类型的任何属性变体。 自定义验证指南可在http://guides.rubyonrails.org/active_record_validations.html#custom-validators
上找到选项2:在property_type_id
模型中添加冗余列variant_properties
,然后添加validates_uniqueness_of :property, scope: :property_type
,就像您已经完成的那样
更新
这是自定义验证器
class VariantProperty < ActiveRecord::Base
belongs_to :property
belongs_to :variant
validate :check_property_type_uniqueness
def check_property_type_uniqueness
errors.add(:property_id, "You cannot have multiple property variants with same property type") if VariantProperty.joins(:property).where(:property_id=>self.property_id,:variant_id=>self.variant_id,:properties=>{:property_type_id=>self.property.property_type_id}).count > 0
end
end
答案 1 :(得分:0)
你应该将PropertyType的关系添加到VariantProperty
class VariantProperty < ActiveRecord::Base
belongs_to :property
belongs_to :variant
has_one :property_type, through: :property
validates :property_type, uniqueness: { scope: :variant_id }
end