如何编写需要在加载一些gem之后运行的代码,但是不需要那个gem?

时间:2014-12-24 20:11:59

标签: ruby rubygems require dynamic-loading

我正在写一个"钩子"到其他宝石。它设计用于处理类似事物的多个不同宝石,这会为可能存在的任何宝石增加功能。

我的宝石在启动时的作用是这样的:

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不在我的宝石的依赖关系中,并且他们可以'在需要的陈述中。

我可以通过在用户初始化A或B或两者之后调用初始化程序时使用MyGem.hook()方法来实现此目的。但我试图避免这种情况。我希望拥有它,这样就可以“添加我的宝石”#34;神奇地"工作

这可能吗?这样做的最佳方式是什么?

我可以以某种方式检查宝石是否在宝石文件"中,并且在这种情况下是否需要模块?

2 个答案:

答案 0 :(得分:1)

您可以通过覆盖require来首先加载您的gem。结合您的代码,当您的宝石加载到其他宝石后,这可以解决问题。像这样:

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 :(得分:1)

不要自动检测代码设置,或做任何过于复杂或“聪明”的事情,在测试和调试时你会后悔(在开发过程中你需要兼容的宝石)依赖关系,并有测试,依次加载每个。相反,请记录您自己的宝石require,以便最终用户根据他们希望的链接加载您的宝石。

因此,假设您的gem被称为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'

根据需要。

对于您的gem用户来说,这不再有用,而且对于使用gem的开发人员和开发人员来说,更容易测试,开发和调试。