将Ruby gem加载到用户定义的命名空间中[英] Load Ruby gem into a user-defined namespace

本文是小编为大家收集整理的关于将Ruby gem加载到用户定义的命名空间中的处理方法,想解了将Ruby gem加载到用户定义的命名空间中的问题怎么解决?将Ruby gem加载到用户定义的命名空间中问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

给定一个定义与我编写的某些代码冲突的顶级类的 gem,是否可以要求 gem 以这样一种方式,即它的所有类都分组在我可以定义的模块中?例如,如果 unsafe_gem 定义了一个类:

class Word
  # ... some code
end

我需要类似的东西:

class Word
  # My word class.
end

module SafeContainer
  # This obviously doesn't work
  # (i.e. the gem still defines ::Word).
  require 'unsafe_gem'
end

这样我可以区分:

Word.new # => The class I defined.
SafeContainer::Word.new # => The class defined by the gem.

更多细节:我的代码(例如"Word"类)已经包装在自己的命名空间中.但是,我希望能够为用户提供启用一种"语法糖"形式的选项,这使得某些类可以在顶级命名空间下直接访问.但是,这会与我正在使用的一个 gem 产生名称冲突,它定义了一个顶级类.当前提出的解决方案都不起作用,因为 gem 实际上依赖于其全局定义的类.所以取消定义类会破坏宝石.当然,gem 有多个文件,单独要求其文件到一个模块中似乎是一个非常脆弱的解决方案.目前,我发现的唯一解决方法是:

begin
  # Require the faulty gem.
  require 'rbtagger'
rescue 
  # If syntactic sugar is enabled...
  if NAT.edulcorated?
    # Temporarily remove the sugar for the clashing class.
    Object.const_unset(:Word); retry
  else; raise; end
ensure
  # Restore syntactic sugar for the clashing class.
  if NAT.edulcorated?
    Object.const_set(:Word, NAT::Entities::Word)
  end
end

我不知道为什么,但这让我的脚趾甲卷曲.谁有更好的解决方案?

推荐答案

另一个可能更好的答案来自 这个问题.

利用类和模块只是对象这一事实,如下所示:

require 'unsafe_gem'
namespaced_word = Word
Word = nil


# now we can use namespaced_word to refer to the Word class from 'unsafe_gem'

#now your own code
class Word
  #awesome code
end

您必须确保 unsafe_gem 只定义一个类,并且在定义自己的类和模块之前 require 它,这样您就不会意外地将自己的东西设置为 nil.

本文地址:https://www.itbaoku.cn/post/786697.html