RSpec为/ lib的子目录中的代码引发NameErrors

时间:2015-03-17 17:42:59

标签: ruby rspec rspec3 ruby-2.2

我有一个具有以下结构的宝石项目:

foo-bar
├── lib
│   └── foo
│       ├── bar
│       │   └── qux.rb
│       └── bar.rb
└── spec
    ├── spec_helper.rb
    └── unit
        ├── baz_spec.rb
        └── qux_spec.rb

lib/foo中,bar.rb定义了一个模块Foo::Bar,在其中定义了一个类Foo::Bar::Baz。在lib/foo/bar内,qux.rb定义了一个类Foo::Bar::Qux

spec_helper.rb设置RSpec和Simplecov,并以require 'foo/bar'结束。 baz_spec.rbqux_spec.rb都以require 'spec_helper'开头。

baz_spec.rb具有Foo::Bar::Baz的规格,并且工作正常。但是,具有qux_spec.rb规范的Foo::Bar::Qux会失败:

/Users/me/foo-bar/spec/unit/qux_spec.rb:6:in `<module:Bar>': uninitialized constant Foo::Bar::Qux (NameError)
    from /Users/me/foo-bar/spec/unit/qux_spec.rb:4:in `<module:Foo>'
    from /Users/me/foo-bar/spec/unit/qux_spec.rb:3:in `<top (required)>'
    from /Users/me/.rvm/gems/ruby-2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1226:in `load'
    ...
    (etc.)

我已经通过将Foo::Bar::Baz的代码移出lib/foo/bar.rb并将其移动到自己的文件lib/foo/bar/baz.rb中来验证这不仅仅是一个错字,之后baz_spec.rb也是class Foo::Bar::Qux ... 停止工作。

我是否将该类声明为

似乎也没有区别
module Foo
  module Bar
    class Qux
      ...

requires

我在Mac OS X Yosemite上使用带有RSpec 3.2.2的Ruby 2.2.0。

显然我的{{1}}有问题,但作为Ruby新手,我没有看到它。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

您需要在foo.rb下添加./lib文件,并为每个文件添加require语句,以便加载它们。您可以查看示例gem以供参考:dogeify以及引导您完成宝石创建的文章build your first gem

答案 1 :(得分:1)

如果你正在使用ActiveSupport,这样的一行会对你有帮助:

ActiveSupport::Dependencies.autoload_paths << "./lib"

如果您现在尝试使用Foo::Bar::Qux,ActiveSupport将在foo/bar/qux.rb文件夹中查找名为lib的文件。

答案 2 :(得分:0)

解决:在仔细研究了我cargo-culting的其他项目之后,我意识到我误解了require

与(显然)其Rails等价物不同,开箱即用的Kernel.require只加载.rb个文件(和扩展库)。因此,在上面的示例中,require 'foo/bar'不会从foo/bar目录加载文件,只会加载foo/bar.rb

为了加载foo/bar下的文件,包括qux.rb,我必须进入bar.rb并在模块声明的顶部显式加载这些文件:

module Foo
  module Bar
    Dir.glob(File.expand_path('../bar/*.rb', __FILE__), &method(:require))

    # ...module declaration continues...

我想,只是众多脚本语言遗留的陷阱中的一个,等待那些从其他更重量级的语言来到Ruby的人。