Gemfile指定gem来源的四种方式

Gemfile的作用无非就是告诉bundler你的项目具体都需要哪些gem,这些gem都需要哪些版本,以及从哪获取这些gem。其实你的问题应该就是跟第三点有关,总的来说,gem的来源可以有四种:

1. 从镜像源安装

这个是最直接的,通过这种方式指定的gem,bundler会从文件开头的source中去查找这个gem:

1
2
source 'https://rubygems.org'
gem 'rails'   # this gem will be installed from https://rubygems.org

2. 从git代码库安装

通过在gem方法(Gemfile实际上就是一个ruby的代码文件)中指定git参数,可以使bundler从指定的远程代码库上拉取代码,比如:

1
2
# nokogiri will be installed from git://github.com/tenderlove/nokogiri.git
gem 'nokogiri', :git => 'git://github.com/tenderlove/nokogiri.git'

3. 从github安装

上面第2种方法只是针对所有合法的git代码库(不仅仅是github,也可以是你自己的一个git服务器上一个代码库)而言,而如果你所需要的库来自于github,则可以通过更方便的github参数实现目标:

1
gem 'nokogiri', :github => 'tenderlove/nokogiri'

可以看到,只要指定了author/repo_name的形式,bundler就能自动从github上获取你所需要的gem了。 注意: 第2跟第3种方式还都可以通过branch参数指定你所需要的代码分支,比如:

1
gem 'refinerycms', github: 'refinery/refinerycms', branch: 'master'

4. 从文件系统中安装

假如你有一个已经放在项目目录中(其实可以是任何地方)的gem,则可以通过path参数指定所需的gem在文件系统中的位置,比如:

1
gem "rails", :path => "vendor/rails"

bundler将会根据path指定的路径去查找并且安装gem。

最后说一下

最后顺便说下我的一点体会,一般像这种gem来自于项目目录下的情况,大多是因为项目中用到了一些提供扩展机制的框架,比如Spree以及Refinery,这两者生成的扩展或者子Engine都是以gem的形式放在vendor或者lib目录下,然后从Gemfile里边进行指定,比如我的一个项目中的一个实例:

1
gem 'refinerycms-factories', :path => 'vendor/extensions'

refinerycms-factories是我用Refinery的generator生成的一个子engine,默认放在verdor/extensions目录下。

另一种可能比较常见的情况就是你用到了某个可能不再维护的gem,由于对源代码的改动较大,所以你干脆把这个gem的源代码下载到本地项目目录下,然后直接进行修改,最后通过path去安装。

参考资料

关于Gemfiile的更多资料,请自行猛戳: Bundler homepage Gemfile manual page

Comments