2014-12-24 15 views
1

我正在写一个“挂钩”到其他宝石上的宝石。它设计用于处理类似事情的多个不同的宝石,这会将功能添加到可能存在的任何宝石中。如何编写需要在加载一些gem后运行的代码,但不需要gem?

什么我做宝石在启动时是这样的:

if defined?(GemAModule) 
    # Hook onto Gem A's observer methods 
end 

if defined?(GemBModule) 
    # Hook onto Gem B's observer methods 
end 

正因为如此,我需要这个代码 A和/或B已经被加载后运行。但是我不能要求A或B.我希望这适用于只使用A或仅使用B的人,因此A和B不在我的gem的依赖项中,并且它们不能处于require语句中。

我可以通过使用:MyGem.hook()方法来实现这一点,用户在初始化A或B或两者之后调用它们的初始值设定项。但我试图避免这种情况。我希望拥有它,以便让我的宝石“神奇”地工作。

这可能吗?做这个的最好方式是什么?

我能以某种方式检查“宝石是否在gemfile中”,在这种情况下需要模块吗?

回答

1

如果您的宝石首先通过覆盖require加载,则可以进行此项工作。结合你的代码在你的宝石加载到其他宝石之后的情况下工作,这应该解决问题。事情是这样的:

module Kernel 
    alias original_require require 

    def require(name) 
    if original_require(name) 
     case name 
     when 'gem_A' 
     # stuff goes here 
     when 'gem_B' 
     # more stuff goes here 
     end 
    end 
    end 
end 

我个人会在这种情况下做的是有你的用户require您在根据不同的方式宝石上,他们使用的是其他宝石,例如:

# if using gem A 
require 'gem_A' 
require 'your_gem/gem_A_compat' 

# if using gem B 
require 'gem_B' 
require 'your_gem/gem_B_compat' 
1

别t自动检测代码设置,或者做任何过于复杂或“聪明”的事情,当涉及到测试和调试(您需要在您的开发依赖关系中需要兼容的宝石,并进行测试,并依次加载)时,您会后悔。相反,记录您自己的宝石的require s,以便最终用户根据他们希望制作的链接加载您的宝石。

因此,假设您的宝石被称为my_gem,你会文件:

的lib/my_gem/gem_a.rb

require 'my_gem' 
require 'gem_a' 
# Require Hook onto Gem A's observer methods 

的lib/my_gem/gem_b.rb

require 'my_gem' 
require 'gem_b' 
# Require Hook onto Gem B's observer methods 

而你指示最终用户require你的宝石如下:

require 'my_gem/gem_a' 

或。 。 。

require 'my_gem/gem_b' 

根据需要。

这对于您的宝石用户来说没有更多的工作,并且更容易为您和使用宝石的开发人员进行测试,开发和调试。