【问题标题】:In Rails 5, how do I inherit from a module I have defined?在 Rails 5 中,如何从我定义的模块继承?
【发布时间】:2020-03-17 22:29:37
【问题描述】:

我正在使用 Ruby on Rails 5。我在 lib/audit/top_level_service.rb 中创建了这个基类

module Audit::Services
  class TopLevelService
    ...
  end
end

在我的应用程序的另一部分,app/services/accounting_service.rb,我想继承我上面创建的这个模块,所以我尝试了

class AccountingService < Audit::Services::TopLevelService
...
end

但这会导致“未初始化的常量 Audit::Services”错误。从我的普通类定义中引用我的基类的正确方法是什么?

【问题讨论】:

    标签: inheritance module ruby-on-rails-5 base-class


    【解决方案1】:

    原因是Autoloading and Reloading Constants。当您尝试访问PerkspotService 时,它没有Audit::Services,也没有文件audit/services.rb。您可以尝试多种方法来解决它。您可以像这样在application.rb 中预定义命名空间:

    Audit = Module.new
    Audit::Services = Module.new
    

    您可以尝试将PerkspotService 包装在如下命名空间中:

    module Audit::Services
      class PerkspotService < TopLevelService
      ...
      end
    end
    

    最后,可以说是正确的方法是遵循提供的链接中描述的规则。您需要将文件路径与定义名称相匹配。所以你 Audit::Services::TopLevelService 需要是一个名为:audit/services/top_level_service.rb 的文件,位于自动加载文件夹之一中。

    【讨论】:

    • 您好@Igor,关于您的“模块 Audit::Services ...”类,路径是什么?我尝试了“app/services/accounting_service.rb”,但在启动 Rails 应用程序或控制台时收到错误消息“`load_missing_constant': Unable to autoload constant CSV::BaseService”。 (也很抱歉重命名,应该从“TopLevelService”继承的类名实际上命名为“AccountingService”)
    • 路径将是:app/services/audit/services/accounting_service.rb。您可以将app/services 或任何其他人视为根,其余应遵循您的名字。它很可能会解决第二个问题。但如果不是你需要使用::BaseService,一开始:: 会说使用顶级范围。否则,它会尝试在当前类/模块中查找常量(如绝对/相对路径)。
    【解决方案2】:

    只需正确地定义它

    # lib/audit/services/top_level_service.rb
    module Audit
      module Services
        class TopLevelService
        end
      end
    end
    

    在定义模块或类时不要使用范围解析运算符::!它不会创建正确的模块嵌套,结果可能非常令人惊讶。 TopLevelService 中的嵌套实际上是::Audit 而不是::Audit::Services。如果Audit::Services 尚未加载,它也会爆炸。

    将它放在lib/audit/services/top_level_service.rb 让自动加载器只加载提供lib 在自动加载路径中的文件。

    【讨论】:

    • 谢谢@max,但是如果我希望我的文件路径是“app/services/top_level_service.rb”而不是“lib/audit/services/top_level_service.rb”,我将如何构建?
    • 您必须将文件放在app/services/audit/services/top_level_service.rb。我会把它放在app/audit/services/top_level_service.rb 中。不要与自动加载器作斗争 - 它只会让其他开发人员更难找到您的代码。
    • 把这个类放在app/services/top_level_service.rb 是公然违反最小意外原则的行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 2013-08-20
    相关资源
    最近更新 更多