我的应用程序有3个模型(Foo,Bar和Baz)
class Foo
has_many :bars
class Bar
belongs_to :foo
has_many :bazs
class Baz
belongs_to :bar
我正在尝试找到最直观的方法来验证Baz(价格)中的属性,而不是在Foo(:min_price和:max_price)中设置的限制。 Baz模型中的价格必须介于Foo设定的限制之间。
目前我正在尝试使用自定义PriceLimitValidator实现它:
class PriceLimitValidator < ActiveModel::Validator
def validate(record)
unless ( record.price <= record.bar.foo.max_price && record.price >= record.bar.foo.min_price )
record.errors[:price] << 'Price limit exceeded!'
end
end
end
这会导致NilClass错误,坦率地说,这并不是最简单的解决方案。
任何关于rails初学者的提示?
答案 0 :(得分:1)
可能.bar或.bar.foo不存在。我会以这种方式实现它:
class Foo
validates_presence_of :min_price, :max_price
end
class Baz
belongs_to :bar
has_one :foo, through: :bar
validates_presence_of :foo
def min_price
foo.try(:min_price)
end
def max_price
foo.try(:min_price)
end
end
class PriceLimitValidator < ActiveModel::Validator
def validate(record)
return if record.min_price.nil? || record.max_price.nil?
unless record.price.between?(record.min_price, record.max_price)
record.errors[:price] << 'Price limit exceeded!'
end
end
end
检查Baz和Foo之间的关系。它不能是belongs_to,因为belongs_to假设foreign_key存在于第一个模型中。在这种情况下,您必须定义has_one:through。
我也在Baz模型中实现了min_price和max_price。它是一个方便的模式,允许您缩短方法链。此外,它允许验证器仅检查此属性,而无需了解模型关联。
最重要的是我验证存在:foo和PriceLimitValidator我检查是否定义了min_price和max_price。检查相关对象是否存在,验证者不负责。
当然,您可以根据自己的需要调整逻辑。
答案 1 :(得分:1)
Rails提供基于Ruby范围功能的开箱即用的验证。
例如:
validates_numericality_of :width, less_than: ->(person) { person.height }, :greater_than... etc. }
完整的规范及其无数选项位于:http://apidock.com/rails/ActiveModel/Validations/HelperMethods/validates_numericality_of