Ruby 与 OR 运算符比较 - 奇怪的行为

Ruby comparison with an OR operator - strange behaviour

下面的代码应该是关于 OR 运算符的奇怪 Ruby 行为的一个很好的例子:

  def search_by_name_active
    if request.path == (name_search_registrants_path \
      || new_registrant_path)
      'active'
    end
  end

规格:

  describe "#search_by_name_active" do
    it "should return active if current page is new_registrant" do
      allow(helper.request).to receive(:path).and_return(new_registrant_path)
      expect(helper.search_by_name_active).to eq('active')
    end
  end

这给我一个错误:

 Failure/Error: expect(helper.search_by_name_active).to eq('active')

   expected: "active"
        got: nil

如果我去掉括号:

  def search_by_name_active
    if request.path == name_search_registrants_path \
      || new_registrant_path
      'active'
    end
  end

第一个规范会通过,但下面的规范不会通过:

it "should return nil if current page is not search_by_name" do
  allow(helper.request).to receive(:path).and_return(id_search_registrants_path)
  expect(helper.search_by_name_active).to be_nil
end

 Failure/Error: expect(helper.search_by_name_active).to be_nil

   expected: nil
        got: "active"

卧槽?!除了下面的附加 if 之外,还有其他方法可以编写此逻辑方程式吗?

  def search_by_name_active
    if request.path == name_search_registrants_path
      'active'
    elsif request.path == new_registrant_path
      'active'
    end
  end

这种行为在所有编程语言中都是预期的,而不仅仅是 ruby。为了稍微简化您的示例:

x == (a || b)

...等同于:

(x == a) || (x == b)

第一个表达式正在评估 (a || b) ,然后 将其与 x 进行比较。所以你只比较 x 一个 的值,而不是 both 个值。

用所有编程语言编写此代码的通用方法是使用上面的第二个代码示例。或者换句话说,使用您的具体示例:

if request.path == name_search_registrants_path \
  || request.path == new_registrant_path

或者,有几种 ruby-specific 方法可以缩短此代码:

# Works in any ruby code
if [name_search_registrants_path, new_registrant_path].include?(request.path)

# Works in any rails code
if request.path.in? [name_search_registrants_path, new_registrant_path]

第二个例子是rails-specific,因为它使用了this extension to the core ruby language