TL;DR

  • 不要为Ruby 烦恼;可以同时安装多个版本的gem.
  • 必要时,使用$ gem-based-binary _version_ args符号指定要执行的版本.
  • 如果有指定版本的文件,请使用bundle exec.
gem install rails -v 3.2.13
rails _3.2.13_ new Project2
cd Project2
bundle exec rails server

UPDATE: 2015-06-04

我三年前写过这个问题.部分原因是基于错误的假设,部分原因是自那以后情况发生了变化.感谢@indirect给出了他最初的答案,我想提请大家注意@kelvin更新的(不太上浮的)答案,总结如下.

我的错误假设是:一次只能安装一个版本的gem,因此gems需要隔离名称空间.不是真的.可以同时安装多个版本的gem.从命令行调用时将使用最新的版本,除非您有一个指定版本约束的文件,并通过bundle exec调用该命令,或将版本指定为其第一个参数.

另请参见How can I call an older version of a gem from the commandline? re:下划线版本符号.


Original question:

我有多个项目正在使用不同版本的Rails.我有一个工作流(如下所述),用于使用特定版本的rails创建项目,并将项目彼此隔离.我想try 其他工作流,尤其是使用rbenv而不是RVM,但不清楚如何做到这一点.

QUESTION:当使用rbenvbundler而不是rbenv gemset或rvm时,创建多个rails项目(每个项目使用不同版本的rails)的best current practice是什么?

我有两个rails项目,分别是ProjectA和ProjectB.ProjectA使用rails的一个版本("RailsA")开发,而ProjectB使用另一个版本("RailsB").如何安装这两个版本?

THE GEMSETS APPROACH:当我第一次开始Rails开发时,我使用了RVM.除了支持ruby的多个并发安装之外,RVM还支持多个应用程序.每个项目都有自己独立的gems集合(包括rails本身),称为gems集:

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

注意:由于骨架文件的版本不同,所以项目文件夹中的creation个应该通过使用desired version个rails的rails new命令来完成(IMHO).(也许我应该重新审视这个前提?)

THE BUNDLER APPROACH:我一直在使用rbenv而不是RVM,但我不太清楚工作流程.在README.md中,Sam Stephenson写道,"rbenv不…管理Gemset.Bundler是管理应用程序依赖关系的更好方法."有一个插件(rbenv-gemset)可以获得与rvm的gemsets相同的结果,但Sam显然更喜欢使用Bundler.不幸的是,他没有详细说明工作流程会是什么样子.就连Bundler网站也没有明确地将如何将一个项目与另一个项目隔离的所有要点联系起来.有blogs and gists人前来救援,他们提出了以下~/.bundle/config个文件:

---
BUNDLE_PATH: vendor/bundle

(顺便说一句,我不确定"--"是关于什么的.文件中没有提到它,似乎也没有什么区别.)

这有效地 for each rails项目提供了自己的gems集,将gems存储在ProjectX/vendor/bundle/中.事实上,rails本身将(重新)安装在那里,一旦我运行bundle install次,该项目将完全独立于我环境的其他部分.

But the elephant in the room is the chicken-and-egg problem of creating the rails project folder in the first place!!为了使用RailsA创建ProjectA文件夹,我需要安装rails(及其众多依赖项)first.但当我想创建ProjectB时,我必须切换到使用RailsB.没有Ruby ,我必须做一些严重的升级/降级.不酷.

一个可能的解决方案就是不用担心我使用什么版本的rails来创建ProjectX文件夹.如果我使用rails 3.0创建一个3.2项目,我就可以手动创建app/assets树.但这让我很恼火.难道没有更好的办法吗?

推荐答案

假设您安装了rails 3.1.0,但希望使用未安装的rails 3.2.13创建一个新项目.

假设你想让新项目在~/projects/Project2年内完成.

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

这将为您创建Gemfile,锁定到您在命令行上指定的rails版本.

我故意忽略了为新项目单独保存一份gems的 idea ,因为这违背了Bundler的理念,即将所有gems安装在一个地方.当您运行rails时,Bundler将自动从该中心位置 Select 正确的gem版本.这意味着一个项目可以共享gems,而不是为自己安装一个新的副本.(但是请注意,您安装的每个ruby版本都有自己的gems.这是一件好事,因为原生扩展可能无法跨ruby版本工作.)

您必须更加清楚,因为像rake这样的大多数命令都会加载您安装的最新版本的rake.您需要运行bundle exec rake ...以确保加载了正确的版本.通常情况下,除了rails之外,我会对所有命令运行bundle exec.你可以创建一个别名来缩短它(我使用bex).要使用gem可执行文件实现自动化,可以使用rbenv-binstubs,但仍需注意,运行rubyirb等非gem可执行文件不会自动使用gem文件.

Sidenote:rails new将运行bundle install,它将判断依赖项的最新版本.如果您希望bundlertry 使用当前安装的符合依赖性要求的gems,可以跳过bundle installrails new --skip-bundle,然后在app dir中运行bundle check.

Sidenote 2:假设您想为Project2使用不同于默认版本(例如2.3.0)的ruby版本(例如2.1.8).在这种情况下,按照上面的规定运行gem install将在2.3.0下安装gems,这是浪费时间,因为您需要在2.1.8下再次安装gems.要解决该问题,可以通过环境变量强制命令使用首选版本:

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来设置变量,但我只建议您在shell期间不希望rbenv基于.ruby-version个文件自动切换.很容易忘记您已经设置了变量,当您cd到另一个项目时,它不会使用您期望的版本.

Ruby-on-rails相关问答推荐

在数组中定位不匹配的索引

我可以向 erb 变量插值添加一个类吗?

如何从 New Relic 交易中获取 TraceId?

如何不需要rails/all?

如何保持 en.yml DRY?

Devise + Omniauth - 如何传递额外的参数?

如何为 Rails SimpleForm Select 框设置默认 Select 值

rails 4.0, rake db:sessions:create

设计和强大的参数

Rails 服务对象与 lib 类

Elastic Beanstalk Ruby/Rails 需要安装 git,所以 bundle install 可以工作.. 但不是

rmagick 和 OS X Lion

Groovy/Grails :: Ruby/Rails :: 2011 框架状态

您将 Rack 中间件文件和要求放在哪里?

Rails 3.1 中的 Rails.cache 错误 - TypeError: can't dump hash with default proc

长期运行项目中的 Rebase Rails 迁移

在 Ruby on Rails 中的控制器中获取 URL 的锚部分

如何在rails中正确使用单选按钮?

Sidekiq Rails 4.2 使用 Active Job 还是 Worker?有什么不同

如何拆分长行的 Ruby