我正在编写一个具有多个gem依赖项的gem,其中一个依赖于在新版本中破坏向后兼容性的gem。这让我思考——我不希望我正在构建的gem变成"让人们难以更新应用程序的gem"。我也不想强迫使用我的gem的人必须在他们的应用程序的其余部分中使用它所依赖的特定版本的gem。
一方面,我可以重写这些依赖项中的所有代码,将它们与我的gem捆绑在一起,并将依赖项全部删除,但这似乎有点乏味。有没有什么方法可以简单地将gem依赖项直接包含在我的gem中,然后将它们封装在一个模块中,这样我的打包版本就不会与应用程序其他部分使用的版本冲突?
我不认为通过现有的Ruby工具可以实现您想要的。然而,如果依赖依赖项时的向后兼容性纯粹是语法/用法问题,而不是版本之间的低级差异,那么您就不必导入和维护旧gem的代码。您还有另一个选择:在您的gem中创建一个"shim"层,该层从依赖项的新接口或旧接口提供所需的功能。
在实践中,它可能是这样的,例如,假设Thingy
类的构造函数发生了变化:
module DependencyShim
def new_Thingy( new_style_args )
if thingy_is_new
Thingy.new( new_style_args )
else
Thingy.new( convert_args_to_old_style( new_style_args ) )
end
end
# convert_args_to_old_style() not shown
private
def thingy_is_old
Thingy::VERSION < '1.3.4'
end
def thingy_is_new
Thingy::VERSION >= '1.3.4'
end
end
更好的抽象很可能是可能的,但很难预测,因为我不知道新旧差异的本质,也不知道代码与依赖关系的紧密程度。
如果版本之间有根本性的更改,并且您自己的gem大量使用依赖关系,那么这显然是痛苦的。但即便如此,它可能仍然比在自己的gem中重新实现和维护依赖性痛苦得多。
我建议您考虑让您的gem与最新版本的依赖项兼容,并从长远来看,根据您对用户群的了解,放弃对旧依赖项的支持。所有相关人员都有充分的理由摆脱旧的依赖关系。
假设您使用的是bundler,您可以在Gemfile中指定依赖项的版本,如下所示:
gem "my_dependency", "0.6.1"
还有很多其他选项,比如"版本大于X"等。阅读bundler文档了解更多信息。