【问题标题】:How do I get Rails to stop re-loading my gems?如何让 Rails 停止重新加载我的 gem?
【发布时间】:2009-07-22 15:32:22
【问题描述】:

我有一颗宝石:

# 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"]

知道如何获得我想要的效果吗?

【问题讨论】:

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


    【解决方案1】:

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

    config.cache_classes = true 
    

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

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

    更新2:第三种解决方案(推荐)如果可以在my_gem.rb中加入如下sn-p

    class ActionController::Base
      include MyGem
    end
    

    那么事情应该可以正常工作了,因为您不需要手动将它包含在您的应用程序控制器中。

    【讨论】:

      【解决方案2】:

      如果您将 gem 包含在 environment.rb 中,则不需要将其包含在控制器中。

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

      听起来也一样,您甚至可能想检查RAILS_ENV 的存在和值,以确保针对不同环境的不同行为。

      【讨论】:

      • 我在 environment.rb 中要求它(隐式);我在 ApplicationController 中包括它。这些是非常不同的行动。我想知道为什么 Rails 每次重新加载 ApplicationController 时都会重新加载 gem。这样做的证据是我的猴子补丁消失了。
      猜你喜欢
      • 2014-07-21
      • 1970-01-01
      • 2020-09-05
      • 1970-01-01
      • 2019-12-20
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      • 2019-08-13
      相关资源
      最近更新 更多