新手问题 2024 年我该如何安装 Ruby on Rails ?

ttys000 · 2024年05月27日 · 最后由 oyaxira 回复于 2024年06月01日 · 1025 次阅读

更新 [Tue May 28 13:10:39 CST 2024]

感谢大家的热心帮助。

很遗憾,我目前还没能顺利在本地安装好 Rails,但过程中也学习和了解了很多,现将我的进展和问题整理于下,方便后续朋友了解或协助解决,再次感谢。

未能解决的问题

  • 安装 Rails 失败
执行 `brew install ruby` 成功安装 Ruby 3.3.1,然后执行 `gem install rails -V` 安装 Rails 遇到问题
命令执行后最终会一直 hang 在 creating Makefile 这一步
具体的终端输出请参考: https://gist.github.com/ttys000/72d535a87d966b0383b7b147213b1cab

似乎是安装 `websocket-driver` 这个 gem 失败了
使用 `gem install websocket-driver --debug` 可以看到报了很多 `No such file or directory` 之类的异常
我尝试着用 Homebrew 切换了几个不同的 3.x Ruby 版本,还是会报同样的异常信息
具体日志请参考: https://gist.github.com/ttys000/badd1459f10cc9a033b8826b923ed997
  • 使用 asdf 安装 Ruby 失败
执行 `asdf install ruby 3.3.1` 安装 Ruby
遇到了 `unmarshal message: unexpected end of JSON input` 错误
具体日志请参考 https://gist.github.com/ttys000/eb02d20eb0373e68d1ef00376c4486a3

TLDR;

如果你遇到问题需要详细了解 Ruby 在 macOS M1 上的安装,那么请阅读本节。我的操作系统版本是 macOS Sonoma 14.5

通过版本控制工具 rbenv、rvm、asdf 安装或者使用 ruby-build 安装

强烈推荐使用 asdf 这个版本管理工具,它底层也是使用 ruby-build 进行构建的,但它输出了更完整的日志,方便 debug。

用法非常简单,请查看

asdf 官网:https://asdf-vm.com/guide/getting-started.html

Mark24 的博客:https://mark24code.github.io/ruby/2021/12/24/Ruby%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BAasdf+ruby+gem+bundler+%E6%BA%90%E6%9B%BF%E6%8D%A2.html

GoRails 的教程:https://gorails.com/setup/macos/14-sonoma#ruby

无论是 rbenv 还是 asdf,这些工具本质上都是从源码构建出 Ruby 的,所以对本地构建环境有一定的依赖和要求,主要有:

  • readline, libyaml, gmp, openssl@3(only for Ruby 3.x)

这些依赖库都可以通过 Homebrew 直接安装。如果遇到 openssl 或者 readline 没有找到正确依赖的问题(比如可能你本地有多个 openssl 版本),可以通过配置环境变量的方式解决。

export RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline) --with-openssl-dir=$(brew --prefix openssl@3)"

这些库依赖都可以通过在环境变量中配置指定 flag 的方式解决,仔细看构建过程中的终端输出会有以下类似的内容:

-> ./configure "--prefix=$HOME/.asdf/installs/ruby/3.2.4" --enable-shared --with-readline-dir=/opt/homebrew/opt/readline --with-libyaml-dir=/opt/homebrew/opt/libyaml --with-gmp-dir=/opt/homebrew/opt/gmp --with-ext=openssl,psych,+ --with-openssl-dir=/opt/homebrew/opt/openssl@3

这显示了当前构建使用的依赖库具体位置(如果没有看到这类信息,请尝试加上 verbose 选项,-v / --verbose 等,具体可以 --help 查看)。

  • rustc

没错,rustc 是 YJIT 必要的依赖,不装就不会构建 YJIT 功能。rust 相关工具的安装非常简单,这里就不赘述了。

  • C 编译工具

确保你本地的 Command Line Tool 安装正确,执行以下命令并检查输出:

xcode-select -p

/Applications/Xcode.app/Contents/Developer

有问题可以通过使用 xcode-select 命令的选项 --install 安装或 -r, --reset 重置为默认路径。

构建日志中可能会显示 llvm 相关的错误,比如:

configure: error: something wrong with LDFLAGS="-L/opt/homebrew/opt/llvm/lib"

这是因为 Ruby 在构建的过程中需要用到 clang 这个 C 编译器前端工具,如果本地安装并配置了 llvm 可能会导致构建失败。

请确保使用 Apple clang:

clang --version

Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

并请检查环境变量 LDFLAGS, CFLAGS, CPPFLAGS 中是否含有 llvm 相关的 path,如果有请去掉试试。

以上就是我遇到并解决过的问题,感谢社区的帮助。


原帖

好久没关注 Ruby on Rails 了,前些天看了 Rails 7 的前端 import-map 等前端方案,感慨这个框架居然不仅一直在更新,而且非常与时俱进,于是重新燃起兴趣。

结果花了一上午的时间完成了「从想玩」到「放弃」

没想到都 2024 年了,在 macOS M1 安装 Rails 如此困难,我的系统版本是 macOS Sonoma 14.5

我尝试了:

  • rvm install script, default install with Ruby and Rails(过程中因为没有 arm64 binary,需要从源码编译 Ruby 失败,有看到 openssl 依赖报错,尝试解决未果)
  • rbenv install ruby(也是报编译错误,没细看)
  • brew install ruby(成功安装 ruby 3.3.1,但是接下来 gem install rails 会 hang 在 creating Makefile 这一步,搞不懂为什么,加上 sudo 或者 --user-install 都一样不行)

等,但都失败了。

然后尝试找一些第三方的 all in one installer,比如 railsinstaller.org 仅支持到 macOS 10.8

更离谱的是,我居然发现了这个 rubyonmac.dev,99 刀就为了安装好 Ruby 和 Rails?难以置信。

为啥不用 docker 呢?

参考下大神的文章,很容易就搞起来了 https://geeknote.net/Rei/posts/372

gakki 回复

谢谢,可以先过渡一下。 不过本地开发环境我不喜欢用 Docker 或者 VM 什么的。 另外,这么重视程序员体验和开发效率的语言及框架,怎么能容忍本地环境安装这么困难呢。

(也能理解,可能是社区不太繁荣,没人维护 arm64 相关的 binary 什么的吧,我记得 10 年前我第一次接触 Ruby 和 Rails,还是很顺利的。)

brew --prefix openssl@3
rvm install 3.3.1 --with-openssl-dir=$(brew --prefix openssl)
piecehealth 回复

谢谢,正在尝试,看起来是 work 的。 不知道安装 Rails 是不是还会 hang 住,brew install ruby 也是成功的,但是接下来安装 Rails 就是一直 hang 在 creating Makefile。

ruby-3.3.1 - #compiling - please wait

时间好长哦

还是建议用 docker,以后就不用再折腾环境问题了。自从用了 docker 腰不酸了,膝盖也不疼了,一口气能上 5 楼。

gakki 回复

😅 嗯嗯,看起来是需要的了,根据 4 楼兄弟的方案,目前还是一直卡在 compiling 这一步,--debug 也没看到输出更多信息,就这么卡在这里。

无语的很,洗澡去了,回来直接用 Docker 吧,我投降了。

今天我在群里,提出了类似的问题。

Ruby 在 MacOS 上的安装,有点不友好。

不如 Python、Java 简单粗暴

随便试试,可以用 Ruby build 安装到任意路径,可移除。

# step1: 安装前置依赖
# ruby-build 是安装工具
# openssl@3 readline libyaml gmp 是必要的依赖 
# rust 是 YJIT 必要的依赖

brew install ruby-build openssl@3 readline libyaml gmp rust

# step2: 编译安装
# $HOME/ruby 替换成你要安装的目录
# 搜索到 ruby 需要把 $HOME/ruby/bin 添加到到你的 PATH

ruby-build 3.3.1 $HOME/ruby

长期使用,推荐 asdf 安装,统一管理。ruby 插件的底层依然是 ruby-build

https://asdf-vm.com/

Mark24 回复

是的呢,更何况还有 Rustup 和 Cargo 这么好用的存在。

补一篇《使用 Ruby-build 在 MacOS 上 编译 Portable Ruby》https://ruby-china.org/topics/43710

Mark24 回复

谢谢,我看下

我用 docker 很久了,印象中用 homebrew 也没遇到什么问题。贴的日志太少无法判断。

rails 7.2 将会添加可选的 devcontainer 配置 https://rubyonrails.org/2024/5/24/this-week-in-rails

这比自己写 docker compose 更方便一些,但不是所有编辑器都支持 devcontainer。

docker 起个开发环境开发?

Rei 回复

Homebrew 安装 ruby 确实没问题,我也成功安装了 ruby-3.3.1,下面是我执行命令 sudo gem install rails -V 的输出,会一直 hang 在那里。

HEAD https://index.rubygems.org/

# 此处省略很多 200 的 GET 请求

/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/CHANGELOG.md
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/LICENSE.md
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/README.md
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/ext/websocket-driver/WebsocketMaskService.java
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/ext/websocket-driver/extconf.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/ext/websocket-driver/websocket_mask.c
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/client.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/draft75.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/draft76.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/event_emitter.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/headers.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/hybi.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/hybi/frame.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/hybi/message.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/proxy.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/server.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/driver/stream_reader.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/http.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/http/headers.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/http/request.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/http/response.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/mask.rb
/opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/lib/websocket/websocket_mask.rb
Building native extensions. This could take a while...
current directory: /opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/ext/websocket-driver
["/opt/homebrew/opt/ruby/bin/ruby", "extconf.rb"]
creating Makefile
current directory: /opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/ext/websocket-driver
["make", "DESTDIR=", "sitearchdir=./.gem.20240527-4605-3b0v07", "sitelibdir=./.gem.20240527-4605-3b0v07", "clean"]
current directory: /opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/ext/websocket-driver
["make", "DESTDIR=", "sitearchdir=./.gem.20240527-4605-3b0v07", "sitelibdir=./.gem.20240527-4605-3b0v07"]

# 一直卡在这里
18 楼 已删除
ttys000 回复
  1. 装的时候看下其他桌面有没有弹出 xcode 的安装提示
  2. 命令行终止的时候有没有报其他错误
  3. 预防措施先执行一次 xcode-select --install 再尝试安装 Rails
ttys000 回复

brew 安装的 ruby 不要用 sudo,它安装目录是属于用户的。

Rei 回复
  1. 没有 xcode 提示
  2. 没有
  3. 尝试过了,Command line tools are already installed.
Rei 回复

不 sudo 的话会提示没有写权限,如下:

ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /opt/homebrew/lib/ruby/gems/3.3.0/gems/websocket-driver-0.7.6/CHANGELOG.md directory.
ttys000 回复

目录权限错乱了,本来 brew 目录下是 user 权限的,执行过一次 sudo 创建了 root 权限的目录,后续写入卡住了。

删了 /opt/homebrew/lib/ruby/gems/3.3.0/gems/ 重新装 gem 也许有用,但不知道还有没有其他目录权限错乱。不行再删除 ruby 看目录清空了没有,再重新安装 ruby。

Rei 回复

哦,检查了一下,这个 gem websocket-driver-0.7.6/ 的 folder 权限确实是错乱了,我手动修复了权限。重新执行 gem install rails -V 之后的输出跟上面那个加了 sudo 的一样了。最终还是 hang 在那里。也许我再多等等。。。

删掉 /opt/homebrew/lib/ruby/gems/3.3.0/ ,我看一些 build 目录在 gems 外面,应该已经被污染了。

还有我最近处理过一个 Ruby 安装问题是混用了不同的安装器,然后环境变量一团乱,最后把所有安装器卸载干净清理多余的环境变量,再重装 homebrew 和 ruby 解决的。

Rei 回复

我删掉了整个 /opt/homebrew/lib/ruby 然后重新

brew install ruby
gem install rails -V

还是跟原来一样没有进展。

BTW,版本管理工具我用过 rbenv 和 rvm,应该都已经卸载干净了,仔细检查了配置文件。用它们的问题基本跟手动使用 ruby-build 遇到的问题是一样的,所以我也没再用它们了,在尝试用 ruby-build 构建,目前还没成功。

详细见 Mark24 的帖子:https://ruby-china.org/topics/43710

ttys000 回复

看起来只要一编译就卡住?

看看 xcode-select -p 的输出,我的是

/Library/Developer/CommandLineTools

sudo xcode-select --resst 可以重置。

另外编译的时候检查内存和硬盘有没有耗尽。

几年前用 macOS 的时候,只用 Homebrew 安装 Ruby,没感觉啥问题,难道现在的 macOS 不一样了。我不使用 rbenv 或 RVM,混着用可能就乱套了。Ubuntu 我就用 Snap,前提是我很少切换版本。

https://gorails.com/setup/macos/14-sonoma

用 gorails 提供的教程,一步步的搞就好了

确实不如一些用的多的语言方便,比如 Go、Node、Java 基本下载一个包解压就好,最多再配一个 PATH 就能开耍了。

从成本的角度来看可能就是因为用的人少,没什么新人,所以社区也不太 care 这方面吧。

官方文档 https://www.ruby-lang.org/zh_tw/documentation/installation/ 很详细了,容易出现权限问题的也可能是 Bundler。国内网络也是个问题,Homebrew 有时候会卡住,Docker 也会。

willx 回复

是的

rails 回复

嗯嗯,好的,谢谢。

supabase 回复

好的,谢谢

很遗憾楼主最终没解决,我推测问题是出在编译工具和环境,这个换什么管理工具都是一样的。但不实地操作我也不知道怎么修复。

我要补充一下,对于新手来说最简单的方法是使用 homebrew:

brew install ruby

为了配合某些 Rails 教程版本,brew 可以安装特定版本 Ruby:

brew install [email protected]

brew 也可以安装 libpq libvips 之类的编译依赖,对于初学环境已经够用。

如果要维护老项目,需要安装特定的包和依赖,去用 docker 和 docker compose,这是终极方案。

如果不是很熟悉 Linux 环境或者机器性能不好,别用 rvm、rbenv、asdf 这类基于环境变量的版本管理工具,很容易把环境变量搞得一团糟。

Rei 回复

homebrew 学习 Rails 实际上并不是很好。

以 我的环境为例 MacOS 13.6.6(Intel) 为例

1)brew install ruby 确实可以正确安装 ruby

他的位置在 /usr/local/opt/ruby/bin/ 都添加到 path。Ruby 自己的组件:ruby、gem、irb 都工作正常

2)当你 gem install rails,正常安装成功,如果你什么都不做,你根本找不到 rails,rails 无从执行。

因为它的位置在 /usr/local/lib/ruby/gems/3.3.0/bin/ ,你需要自己添加到 PATH。 这对新手并不友好。位置在 M1(ARM) 系列的位置可能还不同。这个 PATH 谁来告知?搜索引擎 maybe。。。

实际上,用户得非常留意安装信息里面,才能看到这句;或者说很熟悉 homebrew,再去用 brew info ruby 重新获取。

By default, binaries installed by gem will be placed into:
  /usr/local/lib/ruby/gems/3.3.0/bin

而且这个丑陋的 PATH 还依赖固定版本。

用户还得 会点 vim,maybe shell,知道当前终端是什么,初始化文件在哪儿,还得用 source。 而这一切默认你已经会了。新人不会被告知。 :(


ASDF 帮助解决了 python、ruby、nodejs ……

  • 1) 需要需要构建,需要的前置依赖
  • 2)用户的环境情况,配置的文档
  • 3)初始化
  • 4)这些语言各自的包管理 安装对应包,添加 PATH,动态切换 PATH 的问题。初始化一次,再也不用关心
Mark24 回复

从完全新手的角度来看,你说的确实有一定说服力。拿我这两天的折腾来说,需要不断的 brew install / uninstall, 安装后需要在 .zshrc 里配置 PATH,卸载后还需要手动清除 /opt/homebrew/lib/ruby 下的残留,如果不熟悉 Homebrew、不熟悉 shell、不认真看 Homebrew 的终端输出的话,可能确实会感觉繁琐又混乱。

我用了 asdf 后真的是一下就喜欢上了,当即把自己的 nodejs 也换成了 asdf 管理。

所以这就是为什么我还是仍然纠结在 asdf install ruby 失败的问题上,而不是因为 Homebrew 安装成功了 Ruby 就停止去折腾 asdf。

TLDR; 这节中,我仍然强烈推荐首选使用 asdf 进行 Ruby 的安装和管理,毕竟很多人直接就成功了,没有遇到编译错误。

我太久没用 brew 了,确实忘了要执行这个:

If you need to have ruby first in your PATH, run:
  echo 'export PATH="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc

如果只想用 brew 管理的最新版本 ruby,就不需要用带版本号的 PATH。

如果你用某一个管理工具安装成功了,那很好,先继续学习。

我在这些管理工具踩过不少坑,怕了这些自动改环境变量的工具,再也不想花时间在这上面了。

Rei 回复

是的,应该是编译工具和环境的问题,与上层安装工具无关。

Homebrew 就是切换版本的话是有一些繁琐,站在很新手的角度来看可能确实如 Mark24 所言。如果 asdf 可以正常工作,我个人还是 prefer asdf 一些。

用 Docker 的话对于专业的 Rails 工程师也许是好的实践,项目之间隔离的比较干净,然后还可以尽量靠近生产环境,我目前不用有这么几个原因:

  • 我只是玩一下 Rails,没有那么多项目,所以希望开发环境可以尽量轻薄,少依赖其他服务,项目打开随手就用,不是 compose up 若干个容器
  • 如果 Ruby 和 Rails 都在 Docker 里,那写代码的时候最好是 editor 支持 devcontainer 吧,不然开发体验不太好,这又进一步限制了开发工具是吧?
  • 本地没有 Rails,如何创建一个 Rails 项目?先使用某个已经写好的 Compose 启动一个容器,然后再用这个容器创建出新的 Rails 项目容器,就玩一下来说,感觉也挺折腾的

总的来说 Docker 这个方案不是我想要的那种开发体验。

ttys000 回复

实际上 Rails 官方有个基于 docker 的命令行工具,适合体验用:

https://github.com/rails/docked

安装:

docker volume create ruby-bundle-cache
alias docked='docker run --rm -it -v ${PWD}:/rails -u $(id -u):$(id -g) -v ruby-bundle-cache:/bundle -p 3000:3000 ghcr.io/rails/cli'

使用:

docked rails new weblog
cd weblog
docked rails generate scaffold post title:string body:text
docked rails db:migrate
docked rails server
Rei 回复

这个体验看起来好了很多,赞。

用 brew 装过 php,非常方便

Mark24 回复

我也用的 ASDF 管理 Ruby|Golang|Node,体验还不错😀

Mark24 回复

实际上,用户得非常留意安装信息里面,才能看到这句;或者说很熟悉 homebrew,再去用 brew info ruby 重新获取。

这里告知你了。

而这一切默认你已经会了。新人不会被告知。 :(

做为开发人员(无论新旧),都应该留意 console 输出,无论你熟悉还是不熟悉,共勉吧。

其实安装 rvm 就好了。装完 rvm 基本 ruby 相关依赖就全搞定了。多版本问题也解决了。 rvm 也有提到需要的编译依赖。

ttys000 关闭了讨论。 06月01日 23:08
需要 登录 后方可回复, 如果你还没有账号请 注册新账号