如何让Rails停止重新加载我的宝石?

时间:2009-07-22 15:32:22

标签: ruby-on-rails ruby development-environment monkeypatching

我有一个宝石:

# in /Library/Ruby/Gems/1.8/gems/my_gem-1.0.0/lib/my_gem.rb
module MyGem
  def do_stuff
    ..
  end
end

我在Rails中加载它:

# in [rails_root]/config/environment.rb:
config.gem 'my_gem', :version => '1.0.0'

并使用它:

# in [rails_root]/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include MyGem
end

但我需要以环境特定的方式对它进行修补:

# in [rails_root]/config/environments/development.rb:
MyGem.class_eval do
  def do_stuff
    raise 'Ack! - just testing'
  end
end

不幸的是,MyGem会在每次请求时重新加载,所以我的修补猴子是没用的。

我已查看load_once_paths

ActiveSupport::Dependencies.load_once_paths
# => ["/Library/Ruby/Gems/1.8/gems/my_gem-1.0.0/lib", "other stuff"]

知道我怎么能得到我想要的效果吗?

2 个答案:

答案 0 :(得分:3)

似乎您正在开发模式下,Rails在每个请求中加载所有类,以帮助开发人员反映代码更改+您已将gem包含在控制器中。要解决这个问题,请转到project_path / config / environments / development.rb并添加此行

config.cache_classes = true 

请注意,除非重新启动服务器,否则不会反映您的代码更改。

更新1 : 另外,作为第二种解决方案,您可以在将控制器中包含gem后添加moneky补丁。您可以将其添加到控制器文件的底部。

更新2 :第三种解决方案(推荐)如果您可以将以下代码段添加到my_gem.rb

class ActionController::Base
  include MyGem
end

然后事情应该有效,因为您不需要手动将其包含在应用程序控制器中。

答案 1 :(得分:0)

如果您在environment.rb中加入了宝石,则不需要将其包含在控制器中。

您可能想要考虑gem如何挂钩到ActionController中 - 听起来您想要将类方法添加到ActionController :: Base,这非常简单。看看有多少常见的宝石实现了这一点。

这听起来也像你甚至想要检查存在与否值RAILS_ENV以确保不同环境的不同行为。