Ruby on Rails 3 - 为每个请求重新加载lib目录

Nic*_*ume 58 ruby-on-rails reload rails-engines ruby-on-rails-3

我正在为rails 3应用程序创建一个新引擎.您可以猜到,此引擎位于我的应用程序的lib目录中.

但是,我在开发它时遇到了一些问题.实际上,每次我更改引擎中的内容时,我都需要重新启动服务器.

有办法避免这种情况吗?

我可以强制rails完全重新加载lib目录或特定文件以及他对每个请求的要求吗?

谢谢你的帮助 :)

Pat*_*gan 49

我无法获得上述任何功能,因此我在Rails代码中挖了一下并想出了这个:

新文件:config/initializers/reload_lib.rb

if Rails.env == "development"
  lib_reloader = ActiveSupport::FileUpdateChecker.new(Dir["lib/**/*"]) do
    Rails.application.reload_routes! # or do something better here
  end

  # For Rails 5.1+
  ActiveSupport::Reloader.to_prepare do
    lib_reloader.execute_if_updated
  end

  # For Rails pre-5.1 
  ActionDispatch::Callbacks.to_prepare do
    lib_reloader.execute_if_updated
  end

end
Run Code Online (Sandbox Code Playgroud)

是的,我知道这很恶心,但这是一个黑客.可能有更好的方法来触发完全重新加载,但这对我有用.我的具体用例是安装在Rails路由上的Rack应用程序,所以我需要它在我开发时进行重新加载.

基本上它的作用是检查/ lib中的任何文件是否自上次加载后发生了变化(修改后的时间戳),然后在它们发生变化时触发重新加载.

我可能还会提到我在config/application.rb中有这个

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Run Code Online (Sandbox Code Playgroud)

默认情况下,确保我的lib目录中的所有内容都被加载.

Yays!

  • @pbhogan FileUpdateChecker #initialize的方法签名在Rails 3.2.x中有所改变.摆脱`true`,一切都应该再次正常工作. (5认同)
  • 在Rails 5.1+中,不推荐使用ActionDispatch :: Callbacks.to_prepare,而推荐使用ActiveSupport :: Reloader.to_prepare。 (2认同)

shi*_*ime 33

TL; DR

  • 把它放在config/application.rb中

    config.eager_load_paths += ["#{Rails.root}/lib"]

  • 删除lib文件的require语句

走!


让我详细解释一下.

我不知道为什么这个答案被接受,因为它无助于在每个请求上重新加载lib文件夹.首先我认为它适用于Rails 2,但问题清楚地表明它适用于Rails 3,发布日期3.0.0是在答案日期之前.

其他答案似乎过于复杂或无法提供真正的解决方案.

我决定稍微调查一下,因为它困扰着我,我甚至发现人们有一个解决方法,它涉及将lib文件保存app/models在开发中,然后/lib在完成后移动它.我们可以做得更好,对吗?


我的解决方案经过测试:

  • Rails 3.0.20
  • Rails 3.1.12
  • Rails 3.2.13
  • Rails 4.0.0.rc1

把它放到你的config/application.rb:

# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
Run Code Online (Sandbox Code Playgroud)

就是这样!™

请确保将其放在此处,因为如果将其放入,它将无法工作config/environments/development.rb.

确保删除代码的所有require语句,/lib因为require语句也会导致此解决方案无效.


这段代码隐含地需要你的代码,所以如果你做环境检查(这是不必要的)而不是上面的代码,你决定写这样的东西:

# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?
Run Code Online (Sandbox Code Playgroud)

您应该注意旧require语句,因为在这种情况下,它们仍然需要在所有非开发环境中使用.

因此,如果您仍然决定进行环境检查,请确保对require语句进行反向检查.否则你会被咬伤!

require "beer_creator" unless Rails.env.development?
Run Code Online (Sandbox Code Playgroud)

您可能认为编写关于不必要的内容的整个段落也是不必要的,但我认为警告人们在做一些不必要的事情时所需要的东西也是必要的.

如果您想了解有关此主题的更多信息,请查看此小教程.


小智 21

由于我们正在讨论Rails,最简单的方法是使用' require_dependency '''' '你的lib/*.rb文件.只要控制器/帮助器/ etc(app /下的.rb文件)使用require_dependency而不是只需要重新加载工作,而不需要做任何有趣的事情.

在我走下去之前,唯一有效的解决方案是hemju.com上的解决方案,但我真的不想破解ApplicationController的Dev速度.

  • 适用于Rails 3.2.6.这绝对是最好,最干净的答案. (2认同)

小智 13

你必须添加

config.autoload_paths += %W(#{config.root}/lib)
Run Code Online (Sandbox Code Playgroud)

到config/application.rb中的Application类

https://rails.lighthouseapp.com/projects/8994/tickets/5218-rails-3-rc-does-not-autoload-from-lib

  • 这允许我在lib中的文件被*自动加载*(当你以相同的名称访问常量时加载),但似乎没有帮助它们在每个请求/被修改时被重新加载*.我在Rails 3.2.3上. (15认同)
  • 最好把它放在development.rb中 (3认同)
  • 是的,这个lib中的代码文件是自动加载但没有重新加载,但是当你把文件放在其他地方时它们重新加载:`$:.unshift(config.root); config.autoload_paths + =%w(app/models/misc)`我认为我的lib文件是业务逻辑,我也将业务逻辑放入我的模型中,因此它们是我的模型而不是db-persisted,它是正确的他们在app/models/misc而不是lib中. (2认同)