仅在Ruby中的单个类的上下文中需要gem

时间:2013-08-16 07:16:50

标签: ruby-on-rails ruby gem timeout require

我写了一个宝石,在其中一个类中使用 gem来覆盖Timeout。我只想在这个单一实例中覆盖Timeout,而不是在我的gem中覆盖全局,当然不是在使用我的gem的任何人的项目中全局覆盖。

我遇到的问题是我在rails项目中包含 my gem。似乎超时gem从get-go实例化(在rails app加载)并影响我的Rails应用程序中依赖于标准Timeout的其他部分。

我的问题是:如何将超时gem的影响限制为我希望使用它的单个类。我已经在类定义中放置了require语句,这不是似乎有所帮助。

3 个答案:

答案 0 :(得分:2)

require: false放入您的Gemfile中。 E.g:

 gem 'name-of-gem', require: false

这样,只有在模型中明确调用require 'name-of-gem'时,才会在应用加载时自动生成gem。

(如果这给你错误,你可能会使用旧版本的Ruby,所以你必须写:require => false而不是require: false

答案 1 :(得分:0)

我认为你应该分叉这个gem并为Timeout模块添加一个命名空间,如下所示:

require "timeout"
module NewTimeout
  module Timeout
    #overwrited stuff
  end
end

然后直接在你的宝石中使用它: NewTimeout :: Timeout.timeout() 或者在课堂上加入:

class SomeClass
  include NewTimeout::Timeout
end

默认超时模块保持不变

答案 2 :(得分:0)

如果没有宝石作者的合作,这是不可能的。

当您require文件时,文件中的代码会运行。期。如果文件中的代码monkeypatches一个类或修改全局命名空间或其他什么,那将会发生。周期。

您可以使用load代替require,这样您就可以在匿名模块的上下文中评估文件。但是,当然,使用命名空间操作符::,文件中的代码仍然可以访问全局命名空间及其中的每个模块和类,只需执行类似{{1 }}

现在,如果宝石作者将他的宝石作为class ::String; def length; 42 end end发布,那么你至少能够将效果限制为单个剧本体:

refine

string_with_upper_reverse.rb

module UpperReverse def reverse super.upcase end end module StringWithUpperReverse refine String do prepend UpperReverse end end puts 'Hello'.reverse # olleH using StringWithUpperReverse puts 'Hello'.reverse # OLLEH

test.rb

puts 'Hello'.reverse # olleH require_relative 'string_with_upper_reverse' puts 'Hello'.reverse # olleH using StringWithUpperReverse puts 'Hello'.reverse # OLLEH require_relative 'required'

required.rb

正如您所看到的,puts 'Hello'.reverse # olleH using StringWithUpperReverse puts 'Hello'.reverse # OLLEH require require using refine refine脚本usingrefine都不代表refine在脚本中可见。 明确地refine脚本正文中的refine将使module仅从 开始 >仅一个脚本体中的

但请注意,class是一个实验性功能:在未来的Ruby版本中,它们的API可能会在未经通知的情况下发生变化,甚至可能会完全删除它们。

另请注意,随Ruby 2.0.0一起提供的Module#using版本(以及Ruby 2.1的当前开发版本)只能将 范围限定为脚本实体。在Ruby 2.0.0发布之前不久,删除了范围为Object#sendrefine主体的功能,以及require_relative 'string_with_upper_reverse' using StringWithUpperReverse puts 'Hello'.reverse # OLLEH puts 'Hello'.send(:reverse) # olleH 方法。

最后,请注意{{1}}忽略{{1}}:

{{1}}