管理冲突版本的ruby gems

时间:2011-01-02 17:09:51

标签: ruby plugins rubygems version

我正在构建一个加载用户提供的ruby代码的框架。它基本上是一个插件机制。我希望用户提供ruby代码,以便能够获得自己的宝石。我打算让“插件”包中包含一个包含宝石的供应商目录。

如何加载插件所需的宝石,而不会让它们与我的框架的宝石发生冲突?例如,如果我的框架使用treetop版本1.3.0,并且插件使用treetop 1.4.2我希望每个都使用他们指定的版本。

同样,有没有办法防止插件相互冲突?

我看过gem_plugin,_why的沙箱和其他一些工具。但是我没有看到任何专门处理这种情况的库 - 我认为它之前已经完成了。

我还看了Bundler的内部,看看它如何管理宝石版本。如果需要,我准备做一些非常复杂的事情。但我仍然不确定如何去做。

我对如何实现这一点也有很大的自由。所以,如果你认为我正在咆哮错误的树,请说出来。

感谢您的任何建议。

SIDE注意:在我写这篇文章时,我发现需要类似于Java servlet容器中的类加载器。 WAR文件可以包含jar文件,Web应用程序的类加载器将优先于全局类路径上的jar。有没有办法在ruby中分割ruby“classpath”(即load_path,require等)?

2 个答案:

答案 0 :(得分:5)

说实话,你不能同时加载同一个宝石的两个版本。

Bundler做了很好的(ish)工作,查看所有必需的gem并找到各种重叠依赖项的解决方案,但即便如此,它也只限于一次只加载一个gem版本。

这导致插件开发人员不断更新以支持在依赖宝石中所做的任何更改,以避免您描述的情况。

(不要让我从各种竞争的JSON实现开始搞砸了,当你有几个gem依赖项都需要不同的时候,你必须经历的痛苦。)

答案 1 :(得分:0)

恭敬地不同意上述答案。我是这样做的:

ruby -S gem list my_gem

`*** LOCAL GEMS ***
my_gem (1.0.1, 1.0.0, 0.0.2)
`

ruby -S gem lock my_gem-1.0.0 > locklist.rb

生成特定版本的依赖关系列表到locklist

require 'rubygems'
gem 'my_gem', '= 1.0.0'
gem 'gem_base', '= 1.0.0'
gem 'rest-client', '= 1.7.2'
gem 'savon', '= 1.1.0'
gem 'addressable', '= 2.3.6'
gem 'mime-types', '= 1.25.1'
gem 'netrc', '= 0.11.0'

现在您可以执行load('locklist.rb'),它将加载特定版本的gem及其依赖项。看马,没有Bundler。