1

我有一个具有以下结构的 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,在其中定义了一个类Foo::Bar::Baz。在里面lib/foo/barqux.rb定义了一个类Foo::Bar::Qux

spec_helper.rb设置 RSpec 和 Simplecov,并以require 'foo/bar'. 两者baz_spec.rbqux_spec.rbrequire '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
      ...

我在 Mac OS X Yosemite 上使用 Ruby 2.2.0 和 RSpec 3.2.2。

显然我的 . 有问题requires,但作为一个 Ruby 新手,我没有看到它。有任何想法吗?

4

3 回答 3

2

您需要在下添加foo.rb文件./lib并为每个文件添加要求语句,以便您希望它们被加载。您可以查看示例 gem 以供参考:dogeify和一篇引导您完成 gem 创建的文章构建您的第一个 gem

于 2015-03-17T20:48:42.690 回答
1

已解决:在仔细查看了我所从事的其他项目,我意识到我误解了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 的人所面临的众多脚本语言传统陷阱之一。

于 2015-03-17T20:52:17.163 回答
1

如果您使用ActiveSupport这样的单行代码将对您有所帮助:

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

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

于 2015-03-17T20:13:48.767 回答