如何在建造红宝石宝石时要求上课?

时间:2014-10-17 23:49:08

标签: ruby-on-rails ruby gem

我正在创建一个gem,这是我的结构:

lib/
  | myapp.rb
  | myapp/
      | version.rb
      | configuration.rb
      | use_cases/
      |   base_use_case.rb
      |   entity1/
      |     show_entity.rb
spec/
myapp.gemspec

我想让我的类ShowEntity继承自BaseUseCase。

module MyApp::UseCases::Entity1
  class ShowEntity < BaseUseCase
  end
end

但是我收到以下错误

in `<module:Entity1>': uninitialized constant MyApp::UseCases::Entity1::BaseUseCase (NameError)

在myapp.rb中我需要每个课程,但我仍然会收到错误。

这是我第一次真正理解模块和类如何协同工作并在gem项目中需要它们,因此任何帮助或解释我为什么会遇到错误都会很棒。

1 个答案:

答案 0 :(得分:1)

在您的代码中:

module MyApp::UseCases::Entity1
  class ShowEntity < BaseUseCase
  end
end

Ruby将首先在当前模块BaseUseCase中查找MyApp::UseCases::Entity1。假设此类在MyApp::UseCases下定义以匹配您的文件结构,则不会在那里找到它。 Ruby然后查看封闭范围以尝试查找该类。但是,由于您使用了双冒号语法,因此封闭范围是顶级的, not MyApp::UseCases正如您所期望的那样。 Ruby“跳过”语句module MyApp::UseCases::Entity1中的所有名称空间。

如果您定义了这样的类,它应该可以工作:

module MyApp::UseCases
  module Entity1
    class ShowEntity < BaseUseCase
    end
  end
end

此处,当在当前范围内找不到BaseUseCase时,搜索的封闭范围为MyApp::UseCases。 Ruby一次退回一个module语句,因为现在有Entity1的单独声明,下一个范围是MyApp::UseCases而不是顶级。如果直接在BaseUseCase下定义了MyApp,那么此代码也无效,因为在MyApp::UseCases::Entity1MyApp::UseCases下找不到它之后,搜索的下一个范围将是顶级。

要解决此问题,您应该根据需要细分module声明,或者明确定义BaseUseCase的完全命名空间名称:

class ShowEntity < ::MyApp::UseCases::BaseUseCase