30

我正在使用 Ruby on Rails 并想验证两种不同的模型:

if (model1.valid? && model2.valid?)
...
end

但是,“&&”运算符使用短路评估(即,仅当“model1.valid?”为真时才评估“model2.valid?”),这会阻止在model1 无效时执行model2.valids。

是否存在不使用短路评估的“&&”等价物?我需要评估这两个表达式。

4

6 回答 6

26

试试这个:

([model1, model2].map(&:valid?)).all?

如果两者都有效,它将返回 true,并在两个实例上创建错误。

于 2009-01-28T10:10:36.707 回答
24

& 工作得很好。

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
于 2009-01-28T11:09:03.983 回答
4

怎么样:

if [model1.valid?,model2.valid?].all?
  ...
end

为我工作。

于 2010-06-02T22:44:06.963 回答
2

分别评估它们并将结果存储在变量中。然后在这些布尔值之间使用简单的 && :)

于 2009-01-28T10:01:51.637 回答
0

让未来的开发人员更容易维护代码片段的关键概念之一是它的表现力

让我们考虑以下示例:

([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
于 2021-05-30T15:36:13.380 回答
-1

您可以将一个块传递给all?.

[model_instance_1, model_instance_2].all? {|i| i.valid? }
于 2009-01-28T10:50:36.140 回答