我正在使用Ruby on Rails工作,并希望验证两个不同的模型:
if (model1.valid? && model2.valid?)
...
end
然而,"&&" 运算符使用短路评估(即它只在 "model1.valid?" 为真时评估 "model2.valid?"),这会防止在 model1 无效时执行 model2.valids。
是否有一种不使用短路评估的 "&&" 等效物?我需要对这两个表达式进行评估。
我正在使用Ruby on Rails工作,并希望验证两个不同的模型:
if (model1.valid? && model2.valid?)
...
end
然而,"&&" 运算符使用短路评估(即它只在 "model1.valid?" 为真时评估 "model2.valid?"),这会防止在 model1 无效时执行 model2.valids。
是否有一种不使用短路评估的 "&&" 等效物?我需要对这两个表达式进行评估。
试试这个:
[model1, model2].map(&:valid?).all?
如果两个实例都有效,则返回true,并在两个实例上创建错误。
map(&:valid?)
步骤很重要:[model1, model2].all?(&:valid?)
是一种短路操作(如果 model1
中存在错误,则不会收集 model2
上的错误)。 - Elliot Nelsonall?
,因为它会在第一个 false 时短路,因此你不会在每个模型上得到错误消息。 - Kris& 工作得很好。
irb(main):007:0> def a
irb(main):008:1> puts "a"
irb(main):009:1> false
irb(main):010:1> end
=> nil
irb(main):011:0> def b
irb(main):012:1> puts "b"
irb(main):013:1> true
irb(main):014:1> end
=> nil
irb(main):015:0> a && b
a
=> false
irb(main):016:0> a & b
a
b
=> false
irb(main):017:0> a and b
a
=> false
if [model1.valid?,model2.valid?].all?
...
end
对我来说没问题。
我曾经遇到过类似的问题,需要检查两个字符串是否都不为空。短路运算符阻止了我同时检查两个字符串,但我发现在Ruby中我们可以使用if not或unless。
return nil if not string1.blank? && string2.blank?
或者
return nil unless string1.present? && string2.present?
使得代码片段更易于维护的关键概念之一是其表达能力。
让我们看下面的例子:
([model1, model2].map(&:valid?)).all?
或者
[model1.valid?,model2.valid?].all?
这两个都能很好地完成它们的工作,但是当未来的开发人员在没有看到任何解释性注释、文档或直接联系您的情况下遇到它们中的任何一个时,这个开发人员将修改它们,而不知道目的是为了避免短路评估。
如果没有测试,情况会变得更糟。
这就是为什么我建议引入一个小包装方法,它将立即使所有事情变得清晰明了。
def without_short_circuit_evaluation(*conditions)
conditions.all?
end
然后在你的代码库中的某个地方。
if without_short_circuit_evaluation(model1.valid?, model2.valid?)
# do something
end
不必使用 map 创建额外的数组,你可以向 all?
方法传递一个块。
[model_instance_1, model_instance_2].all? {|i| i.valid? }