【问题标题】:How can I write code that needs to run after some gem was loaded, but without requiring that gem?如何编写在加载某些 gem 后需要运行但不需要该 gem 的代码?
【发布时间】:2015-02-22 20:37:15
【问题描述】:

我正在编写一个“挂钩”到其他宝石上的宝石。它旨在与执行类似操作的多个不同 gem 一起工作,这为可能存在的任何 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 中是否有 gem”,在这种情况下需要模块吗?

【问题讨论】:

    标签: ruby rubygems require dynamic-loading


    【解决方案1】:

    您可以通过覆盖require 在首先加载您的gem 的情况下完成这项工作。结合在其他 gem 之后加载 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 您的 gem,具体取决于他们使用的其他 gem,例如:

    # 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'
    

    【讨论】:

      【解决方案2】:

      不要自动检测代码设置,或者做任何过于复杂或“聪明”的事情,当涉及到测试和调试时,你会后悔的(你需要在你的开发依赖项中同时使用兼容的 gem,并且有测试加载每个反过来)。相反,记录您自己的 gem 的 requires,以便最终用户根据他们希望创建的链接加载您的 gem。

      因此,假设您的 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 您的 gem,如下所示:

      require 'my_gem/gem_a'
      

      或 . . .

      require 'my_gem/gem_b'
      

      根据需要。

      这对于您的 gem 用户来说不再是工作,并且对于您和使用您的 gem 的开发人员来说更容易测试、开发和调试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-20
        • 1970-01-01
        • 2012-09-25
        • 2017-09-17
        • 2015-07-28
        • 2016-04-06
        • 1970-01-01
        相关资源
        最近更新 更多