0

我有一颗宝石:

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

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

4

2 回答 2

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

那么事情应该会起作用,因为您不需要手动将它包含在您的应用程序控制器中。

于 2009-09-22T02:36:19.000 回答
0

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

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

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

于 2009-07-23T00:11:39.403 回答