控制 Rails 验证的顺序
我有一个 Rails 模型,其中有 7 个数字属性,由用户通过表单填写。
我需要验证每个属性的存在,这显然很容易使用
validates :attribute1, :presence => true
validates :attribute2, :presence => true
# and so on through the attributes
,但是我还需要运行一个自定义验证器,它接受许多属性并用它们进行一些计算。如果这些计算的结果不在一定范围内,则该模型应被宣布无效。
就其本身而言,这也很容易
validate :calculations_ok?
def calculations_ok?
errors[:base] << "Not within required range" unless within_required_range?
end
def within_required_range?
# check the calculations and return true or false here
end
,但问题是方法“验证”总是在方法“验证”之前运行。这意味着,如果用户将必填字段之一留空,rails 在尝试使用空白属性进行计算时会抛出错误。
那么我怎样才能首先检查所有必需的属性是否存在呢?
I have a rails model which has 7 numeric attributes filled in by the user via a form.
I need to validate the presence of each of these attributes which is obviously easy using
validates :attribute1, :presence => true
validates :attribute2, :presence => true
# and so on through the attributes
However I also need to run a custom validator which takes a number of the attributes and does some calculations with them. If the result of these calculations is not within a certain range then the model should be declared invalid.
On it's own, this too is easy
validate :calculations_ok?
def calculations_ok?
errors[:base] << "Not within required range" unless within_required_range?
end
def within_required_range?
# check the calculations and return true or false here
end
However the problem is that the method "validate" always gets run before the method "validates". This means that if the user leaves one of the required fields blank, rails throws an error when it tries to do a calculation with a blank attribute.
So how can I check the presence of all the required attributes first?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我不确定是否能保证这些验证按什么顺序运行,因为它可能取决于
attributes
哈希本身的最终排序方式。您可能最好让您的validate
方法更具弹性,并且在缺少某些所需数据时根本不运行。例如:如果变量
a
到d
中的任何一个变量为空(包括 nil、空数组或字符串等),则会退出。I'm not sure it's guaranteed what order these validations get run in, as it might depend on how the
attributes
hash itself ends up ordered. You may be better off making yourvalidate
method more resilient and simply not run if some of the required data is missing. For example:This will bail out if any of the variables
a
throughd
are blank, which includes nil, empty arrays or strings, and so forth.对于稍微复杂的情况,另一种方法是创建一个辅助方法,该方法首先对依赖属性运行验证。然后你就可以进行 :calculations_ok?有条件地运行验证。
我必须为项目创建类似的东西,因为对依赖属性的验证非常复杂。我相当于:calculations_ok?如果依赖属性未正确验证,则会引发异常。
优点:
注意事项:
An alternative for slightly more complex situations would be to create a helper method which runs the validations for the dependent attributes first. Then you can make your :calculations_ok? validation run conditionally.
I had to create something like this for a project because the validations on the dependent attributes were quite complex. My equivalent of :calculations_ok? would throw an exception if the dependent attributes didn't validate properly.
Advantages:
Caveats:
查看 http://railscasts.com/episodes/211-validations-in-rails -3
实现自定义验证器后,您只需
这样做即可解决您的问题。
Check out http://railscasts.com/episodes/211-validations-in-rails-3
After implementing a custom validator, you'll simply do
That should solve your problem.
我记得很久以前就遇到过这个问题,仍然不清楚是否可以设置验证顺序,并且如果验证返回错误,执行链是否会停止。
我认为 Rails 没有提供这个选项。这是有道理的;我们希望显示记录中的所有错误(包括由于输入无效、验证而失败后出现的错误)。
一种可能的方法是仅在要验证的输入存在时才进行验证:
使其美观并使其美观。使用 Rails 惯用的验证选项进行更好的结构化(单一职责):
I recall running into this issue quite some time ago, still unclear if validations order can be set and execution chain halted if a validation returns error.
I don't think Rails offers this option. It makes sense; we want to show all of the errors on the record (including those that come after a failing, due to invalid input, validation).
One possible approach is to validate only if the input to validate is present:
Make it pretty & better structured (single responsibility) with Rails idiomatic validation options:
James H 解决方案对我来说最有意义。然而,需要考虑的另一件事是,如果您对依赖验证有条件,则还需要检查它们才能获得 dependent_attributes_valid?打电话去上班。
IE。
The James H solution makes the most sense to me. One extra thing to consider however, is that if you have conditions on the dependent validations, they need to be checked also in order for the dependent_attributes_valid? call to work.
ie.