Ruby on rails RubyonRails3-为每个请求重新加载lib目录

Ruby on rails RubyonRails3-为每个请求重新加载lib目录,ruby-on-rails,reload,rails-engines,ruby-on-rails-3,Ruby On Rails,Reload,Rails Engines,Ruby On Rails 3,我正在为rails 3应用程序创建一个新引擎。正如您所猜测的,这个引擎位于我的应用程序的lib目录中 但是,我在开发它时遇到了一些问题。事实上,每次更改引擎中的某些内容时,我都需要重新启动服务器 有没有办法避免这种情况 我是否可以强制rails完全重新加载lib目录或特定文件以及每个请求的要求 感谢您的帮助:)在RAILS 3中,以下是自动重新加载lib文件的秘诀。例如,下面的代码有点过火,但这是我为使其工作所做的。您可以在YoYo#gogo中更改消息,并在每次加载页面时在屏幕上看到它。去掉初始

我正在为rails 3应用程序创建一个新引擎。正如您所猜测的,这个引擎位于我的应用程序的lib目录中

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

有没有办法避免这种情况

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


感谢您的帮助:)

在RAILS 3中,以下是自动重新加载lib文件的秘诀。例如,下面的代码有点过火,但这是我为使其工作所做的。您可以在YoYo#gogo中更改消息,并在每次加载页面时在屏幕上看到它。去掉初始值设定项,它保持不变

/config/initializers/lib_reload.rb(新文件)

/app/controllers/home\u controller

require 'yo_yo'
class HomeController < ApplicationController
  def index
    @message = YoYo.new.gogo
  end
end
要求“悠悠”
类HomeController<应用程序控制器
def索引
@message=YoYo.new.gogo
结束
结束
您必须添加

config.autoload_paths += %W(#{config.root}/lib)
到config/Application.rb中的应用程序类

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

注意,在Rails 3中,“加载一次路径”变为“自动加载一次路径”


此外,除非您明确地在其中放置了一些内容,否则它应该是空的。

我无法让上面的任何内容对我起作用,因此我仔细研究了一下Rails代码,得出了以下结论:

新文件:config/initializers/reload_lib.rb

class YoYo
  def gogo
    "OH HAI THERE"
  end
end
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
是的,我知道这很恶心,但这是一种恶作剧。可能有更好的方法触发完全重新加载,但这对我来说很有效。我的特定用例是一个安装在Rails线路上的机架应用程序,所以我需要在开发过程中重新加载它

基本上,它所做的是检查/lib中的任何文件自上次加载以来是否发生了更改(修改的时间戳),然后在更改后触发重新加载

我还可以在config/application.rb中提到这一点

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
默认情况下,它确保我的lib目录中的所有内容都已加载


因为我们谈论的是Rails,最简单的方法是使用“require_dependency”来“require”lib/*.rb文件。只要controller/helper/etc(.rb-files-under-app/)使用require_依赖项,而不是只需要重新加载工作,而不需要做任何奇怪的事情


在我进入这一轨道之前,唯一有效的解决方案是上面的解决方案,但我真的不想为了开发速度而攻击ApplicationController。

另外,确保在application.rb中注释掉以下行(除了@dishod的解决方案),并确保您的模块名与文件名相同(否则,rails将无法找到它)


更新的答案

require 'yo_yo'
class HomeController < ApplicationController
  def index
    @message = YoYo.new.gogo
  end
end
我在我的博客上总结了我的所有发现,你最好看看:

旧答案

require 'yo_yo'
class HomeController < ApplicationController
  def index
    @message = YoYo.new.gogo
  end
end
我也四处寻找解决方案(为了完整性,也为了向其他人指出这个方向),这里是我的发现

从Rails3.1开始,可以通过命令
rails plugin new my_plugin--full
轻松生成引擎。这将生成引擎的框架

--full
表示引擎将被“合并”例如,控制器应该可以直接访问,就像它们是在Include应用程序中定义的一样。这允许您在
my_engine/app/helpers/my_helper.rb
中有一个助手文件,该文件将直接合并到Include应用程序的
app/helpers/my_helper.rb helper

还有另一个选项
--mountable
,它为引擎创建一个名称空间,这样它的控制器等就不会与包括应用程序的控制器发生冲突。这会导致例如,助手位于
my_engine/app/helpers/my_engine/my_helper.rb中,而不会与助手发生冲突
app/helpers/my_helper.rb
in包括你的应用程序

现在更有趣的部分是:

在生成的引擎的
test
文件夹中,有一个
dummy
文件夹,它保存了一个完整的Rails应用程序!它是做什么用的

当你开发一个引擎时,它的功能应该完全独立工作,也应该完全独立测试。因此,在“另一个Rails应用程序”中开发引擎是“错误的”方式(尽管从Rails应用程序中提取现有功能到引擎中时,直觉上这通常是正确的),因此从理论上讲,也不需要在每次请求包含应用程序时重新加载引擎代码

“正确”的方法似乎是这样的:开发和测试你的引擎,就好像它是一个完整的Rails应用,使用
dummy
app!在这里,你可以做任何“正常”的事情Rails应用程序,例如创建使用引擎应提供功能的控制器、模型、视图等。您还可以使用
test/dummy
目录中的
Rails s
启动服务器,并访问
localhost:3000
上的虚拟应用程序,运行测试时,
dummy
应用程序会自动启动用于集成测试。非常好!:-)

你必须小心把你的东西放在哪里:

  • 打算在另一个Rails应用程序中使用的任何功能都会进入
    my_engine/app
    ,而只需要测试引擎功能的任何功能都会进入
    test/dummy/app
然后,您可以轻松地将引擎加载到主应用程序的
Gemfile
中,如下所示:
gem'my\u engine',:path=>'path/to/my\u engine'
或将其作为gem发布到GitHub

(一件有趣的事情(回到本主题)是,当我启动虚拟服务器时,引擎中的所有更改似乎都反映在其中!因此,似乎可以在其中包含一个具有
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?
require "beer_creator" unless Rails.env.development?
  before_filter :dev_reload if Rails.env.eql? 'development'

  def dev_reload
    # add lib files here
    ["rest_client.rb"].each do |lib_file|
      ActiveSupport::Dependencies.load_file lib_file
    end
  end