基本上,你无能为力.这是在Ruby中好的做法,用独特的顶级命名空间的名称正是因为这个原因,你只是偶然发现违反这一做法两个库绊倒.
你可以做的一件事是用Kernel#load而不是Kernel#require.Kernel#load采用可选的布尔参数,它将告诉它在匿名模块中评估文件.但请注意,这绝不是安全的:完全可以将内容显式地放在顶级命名空间中(使用类似的东西module ::PDF),从而打破匿名模块.
另请注意,API非常糟糕:load只需返回,true或者false就像require那样.(实际上,因为load 总是加载,它总是返回true.)没有办法真正进入匿名模块.你基本上必须ObjectSpace手动抓住它.哦,当然,因为没有实际引用的匿名模块,这将是垃圾收集,所以你不仅要在翻找的肠子周围ObjectSpace,以找到该模块,您还可以参加比赛的垃圾收集器.
有时,我希望Ruby有一个合适的模块系统,如Newspeak,Standard ML或Racket.
这个问题可能没有优雅的解决方案。如果您确实需要两个宝石并排工作,我认为您最好的选择是分叉其中一个(或可能两个)并使用您的叉子。这就是我的做法:
.gemspec存储库的根目录中有一个文件,否则下一步将无法进行。使用Bundler来管理项目依赖项。而不是指定对您已修改的库的依赖关系
gem 'the_gem'
Run Code Online (Sandbox Code Playgroud)
像这样指定它:
gem 'the_gem', :git => 'git://github.com/you/the_gem.git'
Run Code Online (Sandbox Code Playgroud)
(但将存储库的 URL 更改为实际的 URL)
向您修改的 gem 的维护者发送一封电子邮件,并要求他或她考虑在下一个版本中合并您的更改。
Bundler 使使用 gem 的替代版本变得非常容易,并且麻烦最少。我经常分叉 gem,修复错误或添加功能,将 my 更改Gemfile为指向我的版本,然后要求维护者合并我的更改。当这种情况发生时,或者如果发生这种情况,我只需更改Gemfile为仅引用 gem 的官方版本即可。
如果维护者不想合并您的更改并且您想将您的版本分发给其他人,则另一种策略是将您的版本作为新 gem 推送到 Rubygems,但在这种情况下,在 gem 名称前加上您的名字,或者其他一些将您的宝石标识为变体的字符串。