【问题标题】:Rails3 not reloading code in lib while in development modeRails3 在开发模式下不会重新加载 lib 中的代码
【发布时间】:2011-04-30 10:41:09
【问题描述】:

情况:

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

    module Foo
      class Bar
        def test
          "FooBar"
        end
      end
    end
    
  2. 在我的助手FooBarHelper 中,我有:

    require `lib/foo/bar`
    module FooBarHelper
      def test_foo_bar
        fb = Foo::Bar.new
        fb.test
      end
    end
    
  3. 在我看来,我这样称呼这个辅助方法:

    <%= test_foo_bar =>
    
  4. 在我的config/environments/development.rb 中,我将目录添加到了我的config.autoload_paths

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

问题:

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

由于我处于开发模式,代码不应该在每次请求时重新加载代码吗?

谁能告诉我我错过了什么?

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 autoload


    【解决方案1】:

    以前的答案无效。这是一个有效的:http://ileitch.github.com/2012/03/24/rails-32-code-reloading-from-lib.html

    你必须同时使用:

    config.watchable_dirs['lib'] = [:rb]
    

    require_dependency
    

    但是任何基于config.autoload_paths 的解决方案都不能在Rails 中工作~> 3.2

    【讨论】:

    • 我绝对认为这应该是公认的解决方案。我花了最后半个小时来搜索这个,因为自动加载整个 lib 目录感觉很脏。
    • 感谢您的回答,迈克。问题是第一个答案是在 Rails 3.1 可用的时候给出的。但是,我承认您的回答也是正确的。我给了你一个赞成票,但也许你可以为 Rails > 3.2 创建一个新问题并自己回答。
    • 我将 config.watchable_dirs['lib'] = [:rb] 放入 development.rb 并在我的控制器中使用 require_dependency "my_folder\my_class"lib\my_folder\my_class 中引用我的类。请参阅apidock.com/rails/v3.2.8/ActiveSupport/Dependencies/Loadable/… 了解更多信息。
    • 我对此表示赞成,因为它发现了一个很少提及的配置选项 (watchable_dirs)。但是,它在 Rails 4.0.0 中对我不起作用。如果我省略了config.autoload_paths,它甚至找不到库,而且你也没有解释如何告诉Rails 去哪里而不是通过autoload_paths。你惹$:什么的?此外,require_dependency 出现 superclass mismatch for class 错误。
    • 好的,我将其归结为子类化 Struct.new(...) 导致的怪异。一旦我消除了这一点,只需设置config.autoload_paths,自动加载和重新加载都可以很好地工作。
    【解决方案2】:

    他们删除了 Rails 3 中应用程序根目录中的 lib 文件夹。

    您可以将其添加回来
    config.autoload_paths << 'lib'
    
    或者你可以在你的助手中使用`require_dependency`。
    module FooBarHelper
      require_dependency 'foo/bar'
    
      def test_foo_bar
        fb = Foo::Bar.new
        fb.test
      end
    end
    

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

    【讨论】:

    • 感谢塞缪尔的回复!我不是已经在使用您的第一个建议了吗?我应该使用&lt;&lt; 运算符而不是+= 吗?我认为它们是等价的。
    • 出于您的目的,它们是相同的。不同之处在于您希望自动加载 lib 以便它能够找到常量 Foo::Barfoo/bar.rb 源文件。
    • 我更新了帖子的情况部分,以便更容易区分。见第 4 部分。
    • 您还有require 声明吗? Rails 不会阻止您请求文件并阻止它重新加载它们(想想您没有编写的库)。如果你使用自动加载,你不能使用 require 并且必须让 rails 来做。否则,如果您不想自动加载 lib 文件夹,请使用 require_dependency
    • 不错! require_dependency 会自动重新加载吗?我还设法应用了您所说的关于自动类映射的内容,这样我就不必通过简单地创建另一个文件夹 foo_lib 并将 foo 放入其中来自动加载整个 lib 文件夹。问题:你从哪里读到这些东西的?因为我肯定想了解更多。
    【解决方案3】:

    在 rails3 中故意禁用了 lib 文件夹中的自动加载代码,有关详细信息,请参阅此 ticket

    Samuel 建议的解决方法是一个很好的开始,但是我发现某些环境仍然难以在测试环境中找到库(比如从黄瓜场景中调用),包括根路径,如ticket 并由 application.rb 中的原始评论暗示是一种更强大的方法:

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

    【讨论】:

      【解决方案4】:

      你为什么把 require 放到模块中,当使用 autoload_path 时你根本不需要 require 文件,它应该可以在没有的情况下工作,我想如果你之后手动 require 文件,rails 不知道什么时候加载再来一次?

      类似这样的:

      require `bar`
      
      module FooBarHelper
      
        def test_foo_bar
          fb = Foo::Bar.new
          fb.test
        end
      
      end
      

      应该可以工作,不需要在你的模块中有 require。

      【讨论】:

      • 感谢马克斯的回复!欣赏它!那么你建议我如何访问我的 Bar 类?
      • 我已经更新了我上面的答案,重新加载对你有用吗?
      • 对不起,我的错误,如果你的加载路径中有 /lib/foo,你只需要在文件中使用 bar。我纠正了我的例子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多