RSpec 为 /lib 的子目录中的代码引发 NameErrors
RSpec raises NameErrors for code in subdirectory of /lib
我有一个具有以下结构的 gem 项目:
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
,并且在其中定义了一个classFoo::Bar::Baz
。在lib/foo/bar
,qux.rb
里面定义了一个classFoo::Bar::Qux
.
spec_helper.rb
设置 RSpec 和 Simplecov,并以 require 'foo/bar'
结束。 baz_spec.rb
和 qux_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 声明为
似乎也没有什么区别
class Foo::Bar::Qux
...
或
module Foo
module Bar
class Qux
...
我在 Mac OS X Yosemite.
上使用 Ruby 2.2.0 和 RSpec 3.2.2
显然我的 requires
有问题,但作为一个 Ruby 新手,我没有发现它。有什么想法吗?
如果您正在使用 ActiveSupport
,像这样的单行将帮助您:
ActiveSupport::Dependencies.autoload_paths << "./lib"
如果您现在尝试使用 Foo::Bar::Qux
,ActiveSupport 将在 lib
文件夹中查找名为 foo/bar/qux.rb
的文件。
您需要在 ./lib
下添加 foo.rb
文件并为每个文件添加 require 语句以便加载它们。您可以查看示例 gem 以供参考:dogeify and an article that walks you through gem creation build your first gem.
已解决:仔细查看了我 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 的人的众多脚本语言继承陷阱之一。
我有一个具有以下结构的 gem 项目:
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
,并且在其中定义了一个classFoo::Bar::Baz
。在lib/foo/bar
,qux.rb
里面定义了一个classFoo::Bar::Qux
.
spec_helper.rb
设置 RSpec 和 Simplecov,并以 require 'foo/bar'
结束。 baz_spec.rb
和 qux_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 声明为
似乎也没有什么区别class Foo::Bar::Qux
...
或
module Foo
module Bar
class Qux
...
我在 Mac OS X Yosemite.
上使用 Ruby 2.2.0 和 RSpec 3.2.2显然我的 requires
有问题,但作为一个 Ruby 新手,我没有发现它。有什么想法吗?
如果您正在使用 ActiveSupport
,像这样的单行将帮助您:
ActiveSupport::Dependencies.autoload_paths << "./lib"
如果您现在尝试使用 Foo::Bar::Qux
,ActiveSupport 将在 lib
文件夹中查找名为 foo/bar/qux.rb
的文件。
您需要在 ./lib
下添加 foo.rb
文件并为每个文件添加 require 语句以便加载它们。您可以查看示例 gem 以供参考:dogeify and an article that walks you through gem creation build your first gem.
已解决:仔细查看了我 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 的人的众多脚本语言继承陷阱之一。