rbenv:没有gemsets的生存

TL; DR

  • 不要打扰gem; 多个版本的gem可能同时安装。
  • 必要时,使用$ gem-based-binary _version_ args表示法指定要执行的版本。
  • 当你有一个指定版本的Gemfile时使用bundle exec
 gem install rails -v 3.2.13 rails _3.2.13_ new Project2 cd Project2 bundle exec rails server 

更新: 2015-06-04

三年前我写了这个问题。 部分原因是基于一个错误的假设,一部分情况从那时起就改变了。 感谢@indirect原来的回答,我想提请注意@开尔文的较新的(不太高效的)答案,总结如上。

我的错误假设:一次只能安装一个版本的gem,因此需要gemset来隔离命名空间。 不对。 多个版本的gem可以同时安装。 除非你有一个指定版本约束的Gemfile,并且通过bundle exec调用命令,或者指定版本作为它的第一个参数,否则最新的一个将在命令行调用时使用。

另请参见如何从命令行调用gem的旧版本? re:下划线版本符号。


原始问题:

我有多个项目正在使用不同版本的Rails。 我有一个工作stream程(如下所述),用于使用特定版本的rails创build项目,并保持项目彼此隔离。 我想尝试其他工作stream程,特别是使用rbenv而不是RVM,但不清楚如何操作。

问题:当使用rbenvbundler时 ,与使用rbenv-gemset或rvm相比,创build多个使用不同版本的rails的多个rails项目的最佳做法是什么?

用例:我有两个rails项目,叫做ProjectA和ProjectB。 ProjectA是使用一个版本的rails(“RailsA”)开发的,而ProjectB使用不同的版本(“RailsB”)。 如何安装两个版本?

GEMSETS方法:当我第一次开始使用Rails开发时,我使用了RVM 。 除了支持多个并发安装的Ruby之外,RVM支持多个命名的Gem Sets 。 每个项目都有自己独立的gem集合(包括rails本身),称为gemset:

 rvm gemset create RailsA rvm gemset use RailsA # RailsA. Note: My question is not version-specific. gem install rails --version 3.0 rails new ProjectA cd ProjectA rvm --rvmrc use `rvm current` vi Gemfile bundle install cd .. ## Now do the same for ProjectB rvm gemset create RailsB rvm gemset use RailsB gem install rails --version 3.2 rails new ProjectB cd ProjectB rvm --rvmrc use `rvm current` vi Gemfile bundle install 

注意:项目文件夹的创build应该通过使用所需版本的rails的rails new命令完成(恕我直言),因为骨架文件的版本不同。 (也许我应该重新审视这个前提?)

捆绑方法:我一直在使用rbenv而不是RVM,但是我不明白工作stream程。 在README.md中 ,Sam Stephenson写道:“rbenv不会pipe理gemset,Bundler是pipe理应用程序依赖关系的更好方法。 有一个插件( rbenv-gemset )可以获得与rvm的gemset相同的结果,但是Sam明显倾向于使用Bundler。 不幸的是,他没有详细说明工作stream程的样子。 即使是Bundler的网站也没有明确地把一个项目与另一个项目隔离开来。 几个博客 和 要点来救援,build议以下~/.bundle/config文件:

 --- BUNDLE_PATH: vendor/bundle 

(顺便说一句,我不确定这个“—”是什么意思,这个文档没有提到它,似乎也没有什么区别)。

这有效地为每个rails项目提供了自己的gemset,将gem存储在ProjectX / vendor / bundle /中。 事实上,一旦我运行bundle install ,rails本身就会(重新)安装在那里,使得项目完全独立于我的环境的其余部分。

在房间里大象是创build轨道项目文件夹的鸡与蛋的问题 为了使用RailsA创buildProjectA文件夹,我需要首先安装rails(及其众多的依赖项)。 但是当我想创buildProjectB时,我必须切换到使用RailsB。 没有gem,我必须做一些认真的升级/降级。 不爽。

一个可能的解决scheme就是不用担心我用什么版本的Rails来创buildProjectX文件夹。 如果我然后使用rails 3.0创build一个3.2项目,我可以手动创build应用程序/资产树。 但是那只是令我烦恼。 没有更好的方法吗?

假设你安装了rails 3.1.0,但是你想使用未安装的rails 3.2.13来创build一个新的项目。

假设您希望新项目位于~/projects/Project2

 gem install rails -v 3.2.13 cd ~/projects rails _3.2.13_ new Project2 

这将为您创buildGemfile ,并locking到您在命令行上指定的导轨版本。

我刻意忽略了为新项目保留一份单独的gem的想法,因为这违背了Bundler的理念,即将所有的gem安装在一个地方。 当您运行rails时,Bundler将从该中心位置自动select正确的gem版本。 这意味着一个项目可以共享gem,而不是为自己安装新的副本。 (不过要注意的是,你安装的每个ruby版本都会有自己的gem,这是一件好事,因为本地扩展可能不会跨越ruby版本)。

你必须要多一点意识,因为大多数命令,比如rake ,都会加载你安装的最新版本的rake 。 你需要运行bundle exec rake ...来确保加载了正确的版本。 通常我会运行除了rails之外的所有命令的bundle exec 。 你可以创build一个别名来缩短它(我使用bex )。 要使用gem可执行文件自动执行此操作,可以使用rbenv-binstubs ,但是仍然需要注意,运行非gem可执行文件(如rubyirb不会自动使用Gemfile。

Sidenoterails new将运行bundle install ,它将检查最新版本的依赖关系。 如果您希望捆绑器尝试使用当前安装的满足依赖项要求的gem,则可以跳过使用rails new --skip-bundlebundle install ,然后在应用程序目录中运行bundle check

旁注2 :假设你想使用与默认值(例如2.3.0)不同的Project2(例如2.1.8)的ruby版本。 在这种情况下,如上所述运行gem install会在2.3.0下安装gems,这是浪费时间,因为你需要在2.1.8下重新安装gem。 要解决这个问题,你可以强制命令通过环境variables使用首选版本:

 RBENV_VERSION=2.1.8 gem install rails -v 3.2.13 cd ~/projects RBENV_VERSION=2.1.8 rails _3.2.13_ new Project2 echo 2.1.8 > Project2/.ruby-version 

可以使用rbenv shell设置variables,但是我只build议如果您不希望rbenv在该shell的持续时间内基于.ruby-version文件进行自动切换。 很容易忘记你已经设置了variables,而当你光盘到不同的项目时,它将不会使用你期望的版本。

大多数人通过安装导轨gem来解决这个问题。 如果你因为某种原因拒绝这么做,你可以selectRails试图为你做的自动绑定。 无论您的rubypipe理系统如何,这都将完全正常工作。

 mkdir myapp cd myapp echo "source :rubygems" > Gemfile echo "gem 'rails', '3.2.2'" >> Gemfile bundle install --path vendor/bundle bundle exec rails new . --skip-bundle 

当出现提示时,input“y”来replace您的Gemfile与默认的Rails之一(或不,如你所愿)。 然后,一旦完成:

 bundle install 

你完成了,你已经用你select的版本boostrapped一个新的rails应用程序,而无需安装rails gem到rubygems。