新手问题 [找到答案,bundle] Ruby 有想 Python 的 virtualenv 工具吗?

eailfly · 2016年01月13日 · 最后由 vanson 回复于 2019年08月29日 · 3918 次阅读

Hi,everyone。 刚接触 ruby,很想知道 ruby 有没有类似 python 的 virtualenv 这样的工具。 我找到一个方法是使用 rvm 的 gemset,但是感觉这样很麻烦的,需要重新安装一个 rvm,更囧的是在我发帖时 arch 上的 ruby 已经到了 2.3.0,而 rvm 里的 ruby-head 才到 2.2.1 是我的方向错了吗?

试试 rvm get head

据我了解 Python 的 virtualenv 对应的是 Ruby 的 bundler http://bundler.io/

rvm get head

就有 2.3 了。

python 与 ruby 这方面的简单类比:

  • (多版本管理器):pyenv <--> rvm
  • (建立在多版本管理器基础上的特定版本加特定包的特定环境,解决系统级别的包依赖):pyenv-virtualenv <--> rvm 的 gemset
  • (特定环境下的包管理器,解决项目级别的包依赖):pip <--> bundler + gem
  • (软件包):whl 包 <--> gem 包

楼主的问题似乎只是多版本管理器的问题?直接用 rvm,或者 rbenv(另一个好用的多版本管理器)就可以解决了。如果是项目的话,就用 bundler。

我想要的不是 rvm 或者 rbenv,事实上我完全没有多版本 ruby 的问题,我想要的是想 python 的 virtualenv 那样,在执行

source bin/activate

后就处于一个完全隔离的环境中了,无论是 easy_install 还是 pip 都不会影响系统环境,只要 deactivate 后在虚拟环境中安装的包是不可见的。 找了一圈,目前发现最接近的方案是使用 bundle,安装时使用

bundler install --binstubs --path vendor

但是这样的方案还是不是很方便,比如安装 rails 后执行 rails 命令必须写全路径才行。

#4 楼 @eailfly 用 bundle 安装以后,加 bundle exec 无需全路径:

bundle exec rails s

恩,貌似也只有这一个办法了

@eailfly 全路径是指 ./bin/rails 么?Ruby 里建议统一都用 bundler 管理,然后用 bundle exec xxx 运行 gem 的命令。如果觉得麻烦,有几个选择:

一是用 binstub 把常用命令放在项目的 ./bin 目录下,然后用 ./bin/xxx 达到 bundle exec xxx 一样的效果。

二是为常用的命令设置 alias。见 Never type bundle exec again 。我个人比较推荐一个脚本 bundler-exec

三是针对 rails 的,直接运行 rails 命令会检测并使用当前项目使用的 rails 版本。所以 rails 命令是不用接 bundle exec 的。不过 bundle everything 是个好习惯。

先补充个链接:ruby-vs-python-packaging-comparison

如果个人理解无误的话,关于 virtualenv,rvm 的 gemset,以及 bundler:

  1. 使用 virtualenv 构建的隔离环境是包含 Python 解释器自身的,这跟 rvm 构建的 gemset 类似;而 bundler 做不到。
  2. 使用 source 激活 virtualenv,与使用 rvm use 激活 gemset 一样,之后的操作都是在指定的环境下进行的,都不会影响系统环境。不知楼主所言似乎这个工具不行,为何?抑或未曾尝试?
  3. 管理项目依赖,Ruby 使用 bundler + Gemfile 的方法;Python 的话,使用 pip + requirements.txt 的方法。
  4. 因为 Ruby 在隔离环境中同一软件包不同版本是可以共存的,通过 bundler 可以指定特定的版本,这样的话,gemset 某些时候似乎显得多余;而 Python 做不到,当你需要安装某版本时,原先的版本会被卸载,因此 virtualenv 显得就非常重要。

整体上,个人觉得 rvm 的 gemset 这个概念,更接近 Python 的 virtualenv,而不是 bundler。但是如第四点指出,单就项目而言,通常都是可以通过 bundler 来解决依赖的,无需 gemset,使用方面 7 楼已经说的非常清楚。

感谢 8 楼,我刚从 python 转过来,对 ruby 的包管理不是很清楚,8 楼很好的解释了两者的区别,之前还是一直按 python 模式处理的,所以才显得非常别扭。 之所以说 gemset 不行只是因为很慢,rvm 需要重新安装一个 ruby,而不是想 virtualenv 那样复制一下就可以了。看样子还是要先学习 bundle 的管理方式。

总结一下常用的开发语言依赖管理工具: Java :Maven,gradle Objective-C :cocoapods https://cocoapods.org/ Swift :Swift Package Manager ,cocoapods,carthage PHP:Composer Python: virtualenv Ruby: bundler https://bundler.io/ Golang: go.mod 官方,低版本 GOPATH C#:nuget https://www.nuget.org/ Node.js:npm https://www.npmjs.com/ Lua:premake https://premake.github.io

为什么 C++ 的构建系统和依赖管理这么混乱? https://www.zhihu.com/question/37316844

需要 登录 后方可回复, 如果你还没有账号请 注册新账号