本文介绍了将Ruby gem加载到用户定义的名称空间中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
给定一个gem,它定义了与我写的一些代码冲突的顶级类,是否有可能要求gem的所有类都被分组在我可以定义的模块中?例如,如果一个unsafe_gem定义了一个类:
class Word
#...一些代码
结束
我需要这样的东西:
class Word
#我的单词类。
end
模块SafeContainer
#这显然不起作用
#(即gem仍然定义:: Word)。
要求'unsafe_gem'
结束
这样我就可以区分:
Word.new#=>我定义的类。
SafeContainer :: Word.new#=>由宝石定义的类。
一些进一步的细节:我的代码(例如'Word'类)已经包装在自己的名字空间中。不过,我希望能够向用户提供启用语法糖形式的选项,这使得可以在顶级命名空间下直接访问某些类。然而,这会与我使用的其中一个宝石产生名称冲突,该宝石定义了顶级类。目前提出的解决方案都没有效果,因为创业板实际上依赖于其全球定义的类在那里;所以没有定义班级打破了宝石。当然,这个gem有多个文件,并且单独将它的文件放入一个模块似乎是一个非常脆弱的解决方案。目前,我发现的唯一解决方法是:
begin
#需要有问题的宝石。
需要'rbtagger'
rescue
#如果语法糖启用...
如果NAT.edulcorated?
#暂时为冲突课程删除糖。
Object.const_unset(:Word);重试
else;提高; end
确保
#为冲突类恢复语法糖。
如果NAT.edulcorated?
Object.const_set(:Word,NAT :: Entities :: Word)
end
end
我不知道为什么,但这会让我的脚趾甲卷曲。任何人都有更好的解决方案?
解决方案 另一个可能更好的答案来自这个问题。
利用这个事实类和模块只是对象,如下所示:
require'unsafe_gem'
namespaced_word = Word
Word = nil
#现在我们可以使用namespaced_word从'unsafe_gem'引用Word类
#找到你自己的代码
class Word
#awesome code
end
您必须确保 unsafe_gem 只定义了一个类,并且在定义自己的类和模块之前需要,这样您才不会意外设置自己的东西到 nil 。
Given a gem that defines top-level classes that clash with some code I have written, is it possible to require the gem in such a way that all its classes are grouped inside a module I can define? For example, if an unsafe_gem defines a class:
class Word
# ... some code
end
I would need something like:
class Word
# My word class.
end
module SafeContainer
# This obviously doesn't work
# (i.e. the gem still defines ::Word).
require 'unsafe_gem'
end
So that I can distinguish between:
Word.new # => The class I defined.
SafeContainer::Word.new # => The class defined by the gem.
Some further details: My code (e.g. the 'Word' class) is already wrapped in its own namespace. However, I want to be able to provide the user with the option of enabling a form of "syntactic sugar", which makes some classes directly accessible under the top-level namespace. This, however, creates a name clash with one of the gems I am using, which defines a top-level class. None of the currently proposed solutions work because the gem actually relies on its globally-defined class being there; so undefining the class breaks the gem. Of course, the gem has more than one file, and individually requiring its files into a module seems to be a very brittle solution. Currently, the only workaround I have found is this:
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
I don't know why, but this makes my toenails curl. Anybody have a better solution?
解决方案
Another, possibly better answer, comes from this question.
Take advantage of the fact that classes and modules are just objects, like so:
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
You have to make sure that unsafe_gem only defines one class, and that you require it before you define your own classes and modules so you don't accidentally set your own stuff to nil.
这篇关于将Ruby gem加载到用户定义的名称空间中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!