1. gemfile的作用
gemfile主要是告诉bundler这个这个项目具体用到了哪些gem,这些gem的版本,来源
2. gem的安装来源方式
首先需要了解,如下source
声明了gem包的默认安装来源
source 'https://gems.ruby-china.org'
1. 从镜像安装
这个是最直接的,通过这种方式指定的gem,bundler会从文件开头的source中去查找这个gem:
# rails will be installed from https://gems.ruby-china.org
gem 'rails'
2. 从git代码库安装
通过在gem方法(Gemfile实际上就是一个ruby的代码文件)中指定git参数,可以使bundler从指定的远程代码库上拉取代码,比如:
# 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参数实现目标:
gem 'nokogiri', :github => 'tenderlove/nokogiri'
第二种和第三种还可以通过, branch参数指定哪个分支
gem 'nokogiri', :github => 'tenderlove/nokogiri', branch: 'master'
4. 从系统安装
假如本机(当然也可以是项目目录中)有所需要的gem则可以通过path参数指定所需的gem在文件系统中的位置,bundler将会根据path指定的路径去查找并且安装gem。
gem "rails", :path => "vendor/rails"
tips:
一般像这种gem来自于项目目录下的情况,大致可以分为两种情况
- 因为项目中用到了一些提供扩展机制的框架
比如Spree以及Refinery,这两者生成的扩展或者子Engine都是以gem的形式放在vendor或者lib目录下,然后从Gemfile里边进行指定,比如我的一个项目中的一个实例:
gem 'refinerycms-factories', :path => 'vendor/extensions'
refinerycms-factories是我用Refinery的generator生成的一个子engine,默认放在verdor/extensions目录下。
- 另一种可能比较常见的情况就是你用到了某个可能不再维护的gem
由于对源代码的改动较大,所以你干脆把这个gem的源代码下载到本地项目目录下,然后直接进行修改,最后通过path去安装。
3. gem的版本设置
首先如果不指定版本,就是默认什么版本都可以
gem "my_gem"
总共有七种操作符用来控制gem版本
= 等于 "=1.0"
!= 不等于 "!=1.0"
> 大于 ">1.0"
< 小于 "<1.0"
>= 大于等于 ">=1.0"
<= 小于等于 "<=1.0"
~> 等于或小范围大于 "~>1.0"
关于 ~>
~> 操作能够让你使用这个gem的未来的某个安全的版本。如果你觉得使用一个大的版本更安全,你能够像下面这样声明.
#允许安装任意的2.x版本的gem,但是3.x版本的不可以,相当于2.0到3.0之间的版本
gem "my_gem", "~> 2.0"
==
gem "my_gem", ">= 2.0", "< 3.0"
或者可以声明一个更具体的版本,如下
#允许安装任意2.5.x版本的gem,相当于2.5.5到2.6.0之间的版本
gem "my_gem", "~> 2.5.5"
==
gem "my_gem", ">=2.5.5","<=2.6.0"
4. gem中的required参数
在项目中的config/application.rb文件里面能看到这么一行代码。
Bundler.require(:default, Rails.env)
或者
Bundler.require(*Rails.groups)
他的意思就是加载gemfile中没有放入group中的gem和当前rails环境(development,production,test)所对应group里面的gem
默认条件下,在gemfile中包含一个gem,当Bundler.require被调用的时候会被包含进来,但是我们也可以设置其不被包含进来(这样你就只是安装了这个gem,但是默认不会加载这个gem,在使用的时候必须在你的代码里手动的添加require ‘my_gem’来调用my_gem里面的方法了),因为并不是所有的地方都需要使用这个gem(比如你在rake task里面使用了my_gem, 而其他地方没有使用,故你只需要把这个gem require到task里面,避免了所有的进程都把这个gem加载进去)
设置gem不被默认加载进来的方法
gem "my_gem", require: false
#默认不会加载这个gem,在使用的时候必须在你的代码里手动的添加require 'my_gem'来调用my_gem里面的方法了
5. group分组
一个gem可以有多个分组,如果没有设置其所属分组,则属于默认分组:default group
两种方式设置分组:
- 给group属性进行赋值,这个gem只在development环境下被require
#这个gem只在development环境下被require
gem "my_gem", group: :development
- 将gem放到block里面
优点是可以设置多个group,也可以同时设置多个gem的所属group
group :development,:test do
gem "my_gem"
gem "my_other_gem"
end
设置分组的好处是
- 设置了分组,在安装时,可以指定某个group下面的gems被安装或不被安装,这样在一定程度上能加快gem的安装,例如
#安装除development和test group下的所有gem
bundle install --without development test
#安装development和test group 下的所有gem
bundle install --with development test
- 设置了分组,在加载gem时,会自动根据当前rails环境require对应group下的gem,避免在不需要的rails环境下require,浪费资源(参考上面第4条中config/application.rb中的Bundler.require释义)
举例如下:
如果当前rails环境是development(开发环境),则项目只会加载development group下面的gem和没有放入group的gem,如果不设置分组的话,则不管是什么rails环境都会加载所有的gem