Object.respond_to?从数组中检索方法名称符号时失败

Object.respond_to? fails when retrieving method name symbol from array

我正在实施页面对象,并编写测试来验证它们。我想通过将元素名称存储在符号数组中并循环遍历它来简化测试,但它失败了。

def setup
  @browser = Watir::Browser.new :phantomjs
  @export_page = ExportPage.new @browser
  @assets = %i{:section :brand}
end

--

#PASSES

def test_static
    $stdout.puts :section.object_id
    raise PageElementSelectorNotFoundException, :section unless @export_page.respond_to? :section
end

> # 2123548

这通过了,因为目标 class 确实实现了这个方法,但是:

#FAILS

def test_iterator
  @assets.each do |selector|
    $stdout.puts selector.class
    $stdout.puts selector.object_id
    $stdout.puts :section.object_id
    raise PageElementSelectorNotFoundException, selector unless @export_page.respond_to? selector
  end
end


> # Testing started at 11:19 ...
> # Symbol
> # 2387188
> # 2123548

PageElementSelectorNotFoundException: :section missing from page
~/src/stories/test/pages/export_page_test.rb:20:in `block in test_iterator'

如您所见,我检查了符号的对象 ID,它们似乎确实不同。这可能是它失败的原因吗?有解决办法吗?

使用短符号声明原子数组时,不应在此处放置冒号:

- %i{:section :brand}   # incorrect
+ %i{section brand}     # correct

@assets = %i{:section :brand}实际定义的是如下数组:

[:':section', :':brand']

不要使用 %i{} 表示法,因为它会自动生成您指定的文字的符号。

这转化为:

@assets = [:":section", :":brand"]

从技术上讲,这是一组符号,而不是您想要的符号。这就是对象 ID 在您的测试中不匹配的原因。

Ruby 2.0 中添加了 %i{} 语法。在可能支持旧 Ruby 版本的代码中使用时,使用传统的符号数组:

@assets = [:section, :brand]