ruby-on-rails 如何避免短路评估

bd1hkmkf  于 2023-05-19  发布在  Ruby
关注(0)|答案(7)|浏览(165)

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

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

然而,“&&”运算符使用短路评估(即,它评估“model2.valid?“只有当”模型1有效吗?“为true),这将防止在model1无效时执行model2.valids。
是否有一个等效的“&&”,它不会使用短路评估?我需要计算这两个表达式。

zpqajqem

zpqajqem1#

试试这个:

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

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

i7uq4tfw

i7uq4tfw2#

&工作得很好。

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
9bfwbjaz

9bfwbjaz3#

怎么样:

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

对我来说很好

piah890a

piah890a4#

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

vkc1a9a2

vkc1a9a25#

使代码片段对未来的开发人员更易于维护的关键概念之一是它的expressiveness
让我们考虑以下示例:

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

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

这两个都做得很好,但是当未来的开发人员在没有看到任何解释性注解、您的意图文档或没有直接联系您的情况下遇到其中任何一个时,这个开发人员将修改它们,而不知道其目的是为了避免短路评估。
当你没有测试时,情况会变得更糟。
这就是为什么我建议引入一个小的 Package 器方法,它可以立即使所有事情变得清晰。

def without_short_circuit_evaluation(*conditions)
  conditions.all?
end

然后在你的代码库中。

if without_short_circuit_evaluation(model1.valid?, model2.valid?)
  # do something
end
nzkunb0c

nzkunb0c6#

我有一个类似的问题,我需要检查两个字符串是否不为空。ShortCircuit阻止了我检查两个字符串,但我发现在Ruby中我们可以使用if not或unless

return nil if not string1.blank? && string2.blank?

return nil unless string1.present? && string2.present?
6kkfgxo0

6kkfgxo07#

您可以将一个块传递给all?,而不是使用map创建额外的数组。

[model_instance_1, model_instance_2].all? {|i| i.valid? }

相关问题