【问题标题】:How can I omit the module name when using autoloaded classes in Ruby on Rails?在 Ruby on Rails 中使用自动加载的类时,如何省略模块名称?
【发布时间】:2012-11-29 22:52:54
【问题描述】:

假设我有以下文件:

|- app
|  |- helpers
|  |  |- application_helper.rb
|- config
|- |- application.rb
|- lib
|  |- my_module
|  |  |- my_class.rb

我正在尝试让 Rails 自动加载 my_module。在application.rb我设置

config.autoload_paths += %W(#{config.root}/lib)

我还设法获得了一个秘密知识,即为了使自动加载起作用,模块和类的名称必须与目录和文件的名称匹配,所以my_class.rb 看起来像这样:

module MyModule
  class MyClass
    # ...
  end
end

现在我想在我的application_helper.rb 中使用MyClass

module ApplicationHelper

  include MyModule

  def some_method(active_entry = nil)
    someobject = MyClass.new
    #...
  end

end

但是我遇到了一个错误

uninitialized constant ApplicationHelper::MyClass

为了使这段代码正常工作,我必须替换

someobject = MyClass.new

someobject = MyModule::MyClass.new

这是丑陋的。我认为include 会像 C++ using namespace、C# using 或 Java import 一样工作,但显然不是。那么 Ruby 中是否有与上述语句等价的语句?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    @ChuckE 很接近,你需要做的是将 config.autoload_paths 更改为

    config.autoload_paths += Dir["#{config.root}/lib/**/"]
    

    以下对我有用

    • 创建目录app/lib/my_module
    • 在那里创建名为my_module.rb的文件

    文件内容:

    module MyModule
      class MyClass
        def self.hello
          puts "Hello"
        end
      end
    end
    
    • 确保config.autoload_paths 如上所述
    • 运行rails console

    输出:

    [tharrison@mbpro:~/Sites/test] rails c
    Loading development environment (Rails 3.2.9)
    1.9.3-p194 :001 > include MyModule
     => Object 
    1.9.3-p194 :002 > MyClass.hello
    Hello
     => nil 
    

    我没有在应用程序中尝试过这个,但看不出为什么它与从 rails 控制台运行有什么不同。

    哦,还有信用到期:从Best way to load module/class from lib folder in Rails 3?得到这个

    【讨论】:

    • 谢谢,它有点工作。只剩下一个问题:这个,以及您之前评论中更丑陋的解决方案,总是在服务器启动后几次失败尝试后开始工作。对于my_module 中的每个类(好吧,实际上有两个)我得到一个一次性错误expected (...)/lib/my_module/my_class.rb to define MyClass。然后我的应用程序完美运行,直到我重新启动服务器。什么鬼?
    • 也可以在我的应用程序中正常工作。 (将puts "Hello"更改为"Hello",然后将include MyModule添加到控制器中,并在索引方法中添加logger.debug "Output from MyClass.hello is #{MyClass.hello}",当我运行时会显示在日志中。您的文件都命名正确吗?
    • 好吧,我复制了你的步骤,创建了一个新的 Rails 项目,但在第一次调用 MyClass.hello 时仍然遇到奇怪的错误。我目前正在从 ruby​​-1.9.3-p286 升级到 ruby​​-1.9.3-p327 看看它是否有帮助,但我必须说我对此表示怀疑。无论如何,如果你没有得到错误而我得到了,那么我想我的 RoR 安装一定是搞砸了:/
    • 非常怀疑新的 ruby​​ 是否会有所帮助。使这项工作发挥作用的所有因素都是相对基本的 ruby​​ 功能,它一直存在。
    • 这个错误开始让我发疯。 This question 向我解释了一些问题 - 似乎 Rails 出于某种原因将 lib/my_module 文件夹视为 root 并希望在那里找到类 MyClass,而不是 MyModule::MyClass。从文件中删除 module 声明可以解决问题。我宁愿将这些类放在一个模块中,但这个解决方案现在必须这样做,否则我会发疯地试图修复它。
    【解决方案2】:

    而不是这个:

    config.autoload_paths += %W(#{config.root}/lib)
    

    试试这个:

    config.autoload_paths += Dir["#{config.root}/lib"]
    

    【讨论】:

    • 没有区别。虽然我会保留这种语法,但我不是%W TBH 的忠实粉丝。
    • 好吧,对我来说,似乎 lib 的子目录没有被包括在内,我认为这会起作用。转到您的控制台并使用 $: 查看您的子目录是否被引用。
    • @kamilk -- 您需要重新启动服务器才能重新初始化。假设您已经这样做了,请尝试将 %W(#{config.root/lib) 更改为 %W(#{config.root}/lib #{config.root}/lib/my_module)。 @ChuckE 提出的不同之处在于添加 Dir 会导致 Rails 搜索整个子树,而简单的数组语法只是枚举要检查的特定目录。所以我认为他的解决方案应该有效。
    • 好的,我已经确认向%W 表单添加另一个路径有效,并且Dir["..."] 不能像ChuckE 那样工作,我认为可以。寻找更优雅的解决方案:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2014-10-20
    相关资源
    最近更新 更多