45

TL;博士

  • 不要为宝石烦恼;可以同时安装多个版本的 gem。
  • $ gem-based-binary _version_ args必要时,使用符号指定要执行的版本。
  • bundle exec当您有一个指定版本的 Gemfile 时使用。
gem install rails -v 3.2.13
rails _3.2.13_ new Project2
cd Project2
bundle exec rails server

更新: 2015-06-04

我三年前写了这个问题。部分原因是基于错误的假设,部分情况从那时起发生了变化。感谢@indirect 的原始答案,我想提请注意@kelvin 的更新(较少赞成)答案,上面总结了。

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

另请参阅如何从命令行调用旧版本的 gem?re:下划线版本表示法。


原始问题:

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

问题:在使用rbenvbundler而不是 rbenv-gemset 或 rvm时,创建多个 rails 项目的最佳实践 是什么,每个项目都使用不同版本的 rails ?

用例: 我有两个 Rails 项目,分别称为 ProjectA 和 ProjectB。ProjectA 是使用一个版本的 rails(“RailsA”)开发的,而 ProjectB 使用不同的版本(“RailsB”)。如何管理安装这两个版本?

GEMSETS 方法: 当我第一次开始使用 Rails 开发时,我使用了RVM。除了支持 ruby​​ 的多个并发安装外,RVM 还支持拥有多个Named 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

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

捆绑器方法:我一直在使用rbenv而不是 RVM,但我对工作流程的理解不是很清楚。在README.md中,Sam Stephenson 写道“rbenv 不......管理 gemsets。Bundler 是管理应用程序依赖项的更好方法。” 有一个插件 ( rbenv-gemset ) 可以获得与 rvm 的 gemsets 相同的结果,但 Sam 显然更喜欢使用 Bundler。不幸的是,他没有详细说明工作流程会是什么样子。甚至Bundler网站也没有明确地将如何将一个项目与另一个项目隔离开来。几个博客 要点来救援,建议以下~/.bundle/config文件:

---
BUNDLE_PATH: vendor/bundle

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

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

但是房间里的大象首先是创建 rails 项目文件夹的鸡与蛋问题 为了使用 RailsA 创建 ProjectA 文件夹,我需要先安装 rails(及其众多依赖) 。但是当我想创建 ProjectB 时,我必须切换到使用 RailsB。如果没有 gemset,我必须进行一些认真的升级/降级。不酷。

一个可能的解决方案就是不用担心我使用什么版本的 rails 来创建 ProjectX 文件夹。如果我然后使用 rails 3.0 创建一个 3.2 项目,我可以手动创建应用程序/资产树。但这让我很恼火。没有更好的方法吗?

4

3 回答 3

42

大多数人通过首先安装 rails gem 来解决这个问题gem install rails。如果您出于某种原因拒绝这样做,您可以选择退出 Rails 尝试为您执行的自动捆绑。无论您的红宝石管理系统如何,这都将完全有效。

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

出现提示时,键入“y”将您的 Gemfile 替换为默认的 Rails 文件(或不替换,根据您的喜好)。然后,一旦完成:

bundle install

您已经完成了,并且您已经使用您选择的版本启动了一个新的 rails 应用程序,而无需将 rails gem 安装到 ruby​​gems 中。

于 2012-03-20T16:39:38.230 回答
12

假设您安装了 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 版本。

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

您必须更加注意,因为大多数命令,例如rake,将加载rake您已安装的最新版本。您需要运行bundle exec rake ...以确保加载了正确的版本。通常我会运行bundle exec所有命令,除了rails. 您可以创建一个别名以使其更短(我使用bex)。要使用 gem 可执行文件自动执行此操作,您可以使用rbenv-binstubs,但您仍然必须注意,运行非 gem 可执行文件(例如ruby并且irb不会自动使用 Gemfile)。

旁注rails new将运行bundle install,它将检查最新版本的依赖项。如果您希望 bundler 尝试使用当前安装的满足依赖要求的 gem,您可以跳过bundle installwith rails new --skip-bundle,然后bundle check在 app 目录中运行。

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

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

于 2013-09-24T16:47:32.980 回答
8

最近有一篇很好的关于 gemsets / bundler 主题的文章http://rakeroutes.com/blog/how-to-use-bundler-instead-of-rvm-gemsets/很好的背景,您可以将其应用于您的 rbenv 设置。

于 2012-03-27T21:30:43.110 回答