Rails3在开发模式下不重新加载lib中的代码

14

情况:

  1. 我有一些代码在lib/foo/bar.rb中,其中定义了一个简单的方法,如下所示:

    module Foo
      class Bar
        def test
          "FooBar"
        end
      end
    end
    
    在我的辅助类FooBarHelper中,我有:
  2. require `lib/foo/bar`
    module FooBarHelper
      def test_foo_bar
        fb = Foo::Bar.new
        fb.test
      end
    end
    
  3. 在我的看法中,我这样调用这个帮助方法:

    <%= test_foo_bar =>
    
    在我的config/environments/development.rb文件中,我向config.autoload_paths中添加了目录。
    config.autoload_paths += ["#{config.root}/lib/foo"]
    

问题:

当我把Foo::Bar.test的返回值改为例如"MODIFIED FOOBAR"时,原始返回值"FooBar"仍然显示在视图中而不是新值。

既然我处于开发模式,难道代码不应该在每个请求时重新加载吗?

请问有人能告诉我我漏掉了什么吗?

谢谢!

4个回答

25

3
我认为这应该是被接受的解决方案。我花了半个小时来搜索它,因为自动加载整个“lib”目录感觉不太好。 - phemmer
谢谢你的回答,Mike。问题在于第一个答案是在Rails 3.1可用时给出的。不过,我承认你的答案也是正确的。我已经给你点了赞,但也许你可以为Rails > 3.2创建一个新的问题并自己回答它。 - John
1
我在development.rb文件中添加了config.watchable_dirs['lib'] = [:rb],然后在我的控制器中使用了require_dependency "my_folder\my_class"来引用位于lib\my_folder\my_class的类。更多信息请参见http://apidock.com/rails/v3.2.8/ActiveSupport/Dependencies/Loadable/require_dependency。 - Sebastian Patten
我点赞了这篇文章,因为它揭示了一个极少提及的配置选项('watchable_dirs')。然而,在Rails 4.0.0中,它对我不起作用。如果我省略了config.autoload_paths,它甚至无法找到库,并且您没有解释如何告诉Rails去哪里查找,而不是通过autoload_paths。你是不是要去弄$:之类的东西?此外,使用require_dependency会出现“类的超类不匹配”的错误。 - Adam Spiers
好的,我把这个问题归结为从子类化Struct.new(...)导致的怪异行为。一旦我消除了这个问题,通过设置config.autoload_paths,自动加载和重新加载都非常好用。 - Adam Spiers

9

在Rails 3中,他们将应用根目录下的lib文件夹删除了。

config.autoload_paths << 'lib'

module FooBarHelper
  require_dependency 'foo/bar'

  def test_foo_bar
    fb = Foo::Bar.new
    fb.test
  end
end

这两种方式都告诉Rails,你的文件 lib/foo/bar.rb 应该被自动加载,并在每个请求后重新加载。


1
你还在使用 require 语句吗?Rails 不会阻止你引入文件并防止其重新加载(比如一些你没有编写的库)。如果你使用自动加载,就不能使用 require,必须让 Rails 来处理。否则,如果你不想自动加载 lib 文件夹,可以使用 require_dependency - Samuel
1
不错!require_dependency会自动重新加载吗?我还成功地应用了你所说的关于自动类映射的方法,这样我就不必通过创建另一个文件夹foo_lib并将foo放入其中来自动加载整个lib文件夹了。问题是:你在哪里读到这些东西的?因为我肯定想多了解一些。 - John
require_dependency 是 Rails 中的一个辅助方法,用于特定加载某些内容并将其标记为可重新加载。 - Samuel
谢谢Samuel。你帮了我很大的忙!我可以问一下你在哪里读到关于自动类名映射的东西吗? - John
自动加载一个模块与类没有什么不同,它应该可以正常工作。你总是可以通过"Mixins::MyMixin".underscore # => "mixins/my_mixin"来查看Rails将要寻找的内容。 - Samuel
显示剩余10条评论

2
Rails3故意禁用了从lib文件夹自动加载代码的功能,详见此票据
Samuel提出的解决方法是一个很好的开始,但我发现在某些环境下仍然难以找到测试环境中的库(例如从cucumber场景调用),并且包括根路径,如票据中所建议的,并由application.rb中的原始评论提示的方法更加健壮。
config.autoload_paths += %W(#{config.root}/lib)

-1

为什么你把 require 放到了模块中,当使用 autoload_path 时根本不需要 require 文件,它应该可以正常工作而无需 require。我认为如果你之后手动 require 文件,Rails 就不知道何时再次加载它。

类似这样的:

require `bar`

module FooBarHelper

  def test_foo_bar
    fb = Foo::Bar.new
    fb.test
  end

end

应该可以工作,不需要在你的模块内部使用 require。


谢谢你的回复,Max!非常感谢!那么你认为我该如何访问我的 Bar 类呢? - John
我已经更新了我的上面的回答,重新加载后是否可以正常工作? - Max Schulze
抱歉我的错误,如果你的加载路径中有/lib/foo,那么你只需要在文件中require bar。我已经更正了我的示例。 - Max Schulze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接