我有一个具有以下结构的宝石项目:
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.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 Foo::Bar::Qux
...
停止工作。
我是否将该类声明为
似乎也没有区别module Foo
module Bar
class Qux
...
或
requires
我在Mac OS X Yosemite上使用带有RSpec 3.2.2的Ruby 2.2.0。
显然我的{{1}}有问题,但作为Ruby新手,我没有看到它。有什么想法吗?
答案 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的人。