Ruby on Rails 開発環境構築 on M1 Mac

# はじめに

※この文章は現在ベータ版です。随時アップデートしていく予定です。

macOSのパッケージ管理ツールHomebrewをつかって、M1チップ搭載Mac(M1 Mac)
上にRuby on Railsの開発環境構築を行う際の手順を書いています。

[M1チップ搭載MacBookPro環境構築手順](https://qiita.com/aiorange19/items/5ffaefc85f912f60c2fa) を参考にしています。

M1 Macでの汎用的な環境構築については [M1 Macの開発環境](https://qiita.com/shibukawa/items/797b7cbb7e530842e6f7) が参考になります。
(パッケージ管理にHomebrewではなくMacPortsを採用しているので、その箇所は
Homebrewによる環境構築ではあまり参考になりません。)

M1 Macでのwith Homebrew な環境構築について [開発環境 on M1 Mac with Homebrew](https://qiita.com/asip2k25/items/7088667e2177ab061dd2) を
書いてみました。

# 事前準備
Homebrew は Xcode の機能を利用して、ソフトウェア群をコンパイルするので、最初に
Xcode と Command Line Tools for Xcode をインストールします。

## Xcode のインストール

AppStore経由でインストールします。

## Command Line Tools for Xcode (CLT) のインストール

Xcodeを起動し、メニューの Xcode => Open Developer Tool => More
Developer Tools をクリックすると表示されるページから、インストールした
Xcodeのバージョンに対応した CLT をダウンロードし、インストールします。

# Homebrewのインストール on M1 Mac

v3.0.0(2021/02/05(日本時間2021/02/06?)リリース)で、
インストーラ及ぶ本体がIntel・M1両対応になっています、
Intel Mac (x86_64パッケージ) では /usr/local 下、
M1 Mac (AppleSiliconパッケージ)では /opt/homebrew 下、
を利用する形に正式になりました。

AppleSiliconパッケージが、従来のインストール先である /usr/local/ 下
ではなく、/opt/homebrew 下へのインストールとなっているのは、 
/usr/local/ 下におくと上手く動作しないケースがあるからのようです。

ユーザーは、Intel Mac or M1 Macをあまり意識することなく、Homebrewを
インストールでき、/usr/local or /opt/homebrew 下にインストール
されたソフトウェア群を利用できるようになっています。

```
v2.7.0では、Rosetta2を利用する場合を除き、従来のインストーラは
利用できず、従来のインストーラとは別に、M1 Mac用のパッケージ(M1 Mac版)
が用意されていました。

M1 Mac版 (v2.7.0)のインストールは、Homebrew一式のtarボールを
/opt/homebrew に展開する手順になっていました。

Intel Mac版を /usr/local 下、M1 Mac版を/opt/homebrew 下に
インストールし、併用することも想定されてはいたようです。
(個人的には、Intel Mac版とM1 Mac版を併用するのはオススメできません。)

Intel Mac版とM1 Mac版をわけ、M1 Mac で /opt/homebrew 下を利用
しているのは、インストーラ及び本体をIntel・M1両対応にするのには時間を
要するため、M1 Macになる早でHomebrewを提供するための一時的な措置の
結果で、Intel・M1両対応後は、/usr/local 下を利用する形に戻される、
と考えていましたが、そうはなりませんでした。
```

# インストール手順

Homebrewをインストールします。

/opt/homebrew へのインストール後は、.zshrc(シェルがzshの場合)に
Homebrewへのパスを追加し、シェルに反映します。

必要なら、/opt/homebrew のログインユーザーへの所有権設定、を行います。
(/opt 下はrootユーザーの管理下にあるので、そのままでは、ログインユーザー
ではいじれません。)

Homebrewへのパスが通っているか確認してから、インストールしたHomebrewを
更新しておきます。

```
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
% vi ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
% source ~/.zprofile
% sudo chown -R $USER $(brew --prefix) # 必要なら
% brew -v
% brew update
```

# rbenv のインストール

rbenvとruby-buildをHomebrewでインストールします。

rbenvへのパスとシェル起動時rbenv初期化コマンドを.zhrc(シェルがzshの場合)
に追加し、シェルに反映します。

RBENV_ROOTにはrbenvのインストールされたディレクトリをセットしています。
このセットでrbenvでのrubyインストール時にrbenvのインストールされた
ディレクトリにrubyがインストールされます。

RBENV_ROOTをセットしていないと、rbenvでのrubyインストール時に
Users/$HOME/.rbenv下にrubyがインストールされます。

rbenvにパスが通っているか確認しておきましょう。

```
% brew install ruby-build
% brew install rbenv 
% vi ~/.zshrc
export RBENV_ROOT=$(brew --prefix rbenv) 
export PATH=$RBENV_ROOT/bin:$PATH
eval "$(rbenv init -)"
% source ~/.zshrc
% rbenv
```

# Ruby のインストール

rubyのインストールにはopensslとreadlineが必要なので、Homebrewで
インストールします。

Ruby3.1以降で YJIT を組み込むには rust が必要なので、Homebrewで
インストールします。

opensslへのパスとrubyコンパイル時に必要な環境変数へのopenssl用の設定を
.zhrc(シェルがzshの場合)に追加し、シェルに反映します。

rbenvでインストール可能なバージョンを確認、インストールするバージョンを
選択し、インストールします。

rbenvのshimsを更新します。

動作させるRubyのバージョンをrbenvで設定します。

設定したバージョンのRubyが動作しているか確認しておきましょう。

```
% brew install readline
% brew install openssl
% brew install rust
% vi ~/.zshrc
export RBENV_ROOT=$(brew --prefix rbenv) 
export PATH=$RBENV_ROOT/bin:$PATH
eval "$(rbenv init -)"

export OPENSSL_ROOT=$(brew --prefix openssl) # openssl@1.1 (Ruby < 3.1)
export PATH="$OPENSSL_ROOT/bin:$PATH"
export LDFLAGS="-L$OPENSSL_ROOT/lib"
export CPPFLAGS="-I$OPENSSL_ROOT/include"
export PKG_CONFIG_PATH="$OPENSSL_ROOT/lib/pkgconfig"
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$OPENSSL_ROOT"
% source ~/.zshrc
% rbenv install --list 
% rbenv install 3.2.2
Installed ruby-3.2.2 to /opt/homebrew/opt/rbenv/versions/3.2.2
% rbenv rehash
% rbenv global 3.2.2
% ruby -v
```

# RubyGems & Bundler のアップデート

RubyにプリインストールされているRubyGemsとBundlerを最新版に更新します。

```
% gem update --system
% gem update bundler
```

# Node.js & Yarn のインストール

Ruby on Railsのプロジェクト内ではJavascriptのパッケージ管理に
Webpacker etcで Node.js と Yarn を利用するので、Node.js と
Yarn もインストールしておきます。

```
% brew install node
% brew install yarn
```

# Bun のインストール (おまけ)

https://bun.sh

Bun は、Ruby7.1から オプションで Node.jsの代わりに採用可能になった
JavaScript実行環境です。

Node.js との高い互換性を目指して開発されています、Node.js より高速に
動作します。今のところ、Node.js と高い？互換ではあるものの完全互換では
ないので、注意が必要です。

https://bun.sh/docs/runtime/nodejs-apis

現時点では、RailsのJSまわり(サードパーティー製のgem etc)において、
Bun は考慮されていないに近いので、自前で何とかできる自信がなければ、
Bun の採用は見合わせたほうが無難です。

モジュールシステムとして、Node.js と同様、CommonJS と ESModule を
採用しています。

# Deno.js のインストール (おまけ)

https://deno.com

Ruby on Railsとは今のところ関係ありませんが、JavaScript
実行環境です。

Deno.jsは、Node.jsとの互換(開発途上)もあり発展途上ではあるものの
Node.jsより洗練されているので、注目しておくことをオススメします。

モジュールシステムとして、ESModule を採用しています。

# libxml2 & libxslt & libiconv のインストール

Ruby on Railsのプロジェクト内でシステムテストにCapybaraを利用
している際にはCapybaraが依存しているNokogiri gemがバックエンドで
利用しているこれらのネイティブ・ライブラリをあらかじめインストール
しておく必要があります。

また、これらのライブラリへのパスとこれらのライブラリを利用した
プログラムのコンパイル時に必要な環境変数への設定を.zhrc(シェルが
zshの場合)に追加し、シェルに反映します。

Homebrewでインストールしたこれらのライブラリをbundlerがnokogiri
インストール時に利用するように設定します。

```
% brew install libxml2 libxslt libiconv
% vi ~/.zshrc
export RBENV_ROOT=$(brew --prefix rbenv) 
export PATH=$RBENV_ROOT/bin:$PATH
eval "$(rbenv init -)"

export OPENSSL_ROOT=$(brew --prefix openssl) # openssl@1.1 (Ruby < 3.1)
export PATH="$OPENSSL_ROOT/bin:$PATH"
export LDFLAGS="-L$OPENSSL_ROOT/lib"
export CPPFLAGS="-I$OPENSSL_ROOT/include"
export PKG_CONFIG_PATH="$OPENSSL_ROOT/lib/pkgconfig"
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$OPENSSL_ROOT"

export LIBXML2_ROOT=$(brew --prefix libxml2)
export PATH="$LIBXML2_ROOT/bin:$PATH"
export LDFLAGS="$LDFLAGS -L$LIBXML2_ROOT/lib"
export CPPFLAGS="$CPPFLAGS -I$LIBXML2_ROOT/include"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$LIBXML2_ROOT/lib/pkgconfig"

export LIBXSLT_ROOT=$(brew --prefix libxslt)
export PATH="$LIBXSLT_ROOT/bin:$PATH"
export LDFLAGS="$LDFLAGS -L$LIBXSLT_ROOT/lib"
export CPPFLAGS="$CPPFLAGS -I$LIBXSLT_ROOT/include"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$LIBXSLT_ROOT/lib/pkgconfig"

export LIBICONV_ROOT=$(brew --prefix libiconv)
export PATH="$LIBICONV_ROOT/bin:$PATH"
export LDFLAGS="-L$LIBICONV_ROOT/lib $LDFLAGS"
export CPPFLAGS="-I$LIBICONV_ROOT/include $CPPFLAGS"
% source ~/.zshrc
% bundle config build.nokogiri --use-system-libraries \
  --with-xml2-include=$(brew --prefix libxml2)/include/libxml2
```

# libffi のインストール

Ruby on Railsのプロジェクト内でシステムテストにSelenium WebDriverを
利用している際にはこのgemが依存しているffi gemがバックエンドで利用して
いるネイティブ・ライブラリをあらかじめインストールしておく必要があります。

また、libffiへのパスとこのライブラリを利用したプログラムのコンパイル時に
必要な環境変数への設定を.zhrc(シェルがzshの場合)に追加し、シェルに反映
します。

```
% brew install libffi
% vi ~/.zshrc
export LIBFFI_ROOT=$(brew --prefix libffi)
export PATH="$LIBFFI_ROOT/bin:$PATH"
export LDFLAGS="-L$LIBFFI_ROOT/lib $LDFLAGS"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$LIBFFI_ROOT/lib/pkgconfig"
% source ~/.zshrc
```

# LibSass のインストール (オプション)

Ruby on Railsのプロジェクト内で Sass/Scss のコンパイルを行う
sass(c)-rails gemを利用している際にはこのGemが利用している
sassc-ruby がバックエンドで利用している LibSass をあらかじめ
インストールしておく必要があります。

Rais5.0 あたりまでは sass-rails が広く利用されていましたが、
このGemが利用している sass-ruby が Sassチーム によりDeprecated指定
されてしまったので、その後、LibSassを利用しているsassc-rails の利用が
推奨されるようになりました。

sass-rails は、2019/03 から、sassc-rails のラッパーに
なっています。
https://github.com/rails/sass-rails/commit/706526d411d2d78e578c7944e873ece28e65ed42

(依存関係: sass-rails → sassc-rails → sassc-ruby → LibSass)

その後、Sassチームが LibSass を Deprecated指定し、Sass の
リファレンス実装であるDart Sass の推奨を発表しました。

[Sass : LibSass is deprecated](https://sass-lang.com/blog/libsass-is-deprecated)

LibSass はメンテナンスモードであり、Sass の新機能の追加はなく、バグFix のみが行われているので、注意が必要です。

esbuild/rollup/webpack 経由での Dart Sass の利用を検討
したほうがよいかもしれません。

```
% brew install libsass
```

# Dart Sass のインストール (オプション)

esbuild/rollup/webpack 経由で Dart Sass を利用する場合
には、あらかじめ、Dart Sass をインストールしておく必要があります。

```
% yarn add sass
```

# libvips or ImageMagick のインストール (オプション)

Ruby on Railsのプロジェクト内で画像のアップロード＆表示を行うGem等を
利用している際にはそれらのGemがバックエンドとして利用しているネイティブの
ライブラリをあらかじめインストールしておく必要があります。

Shrine or ActiveStorage が採用しているimage_processing gemは
バックエンドとしてlibvips or ImageMagickを選択できます、Shrine or ActiveStorageを利用した開発を行う際にはバックエンドとして libvips or
ImageMagick を利用することになります。

CarrierWave が利用している MiniMagick gem はバックエンドとして
ImageMagickを を採用しています。

libvips のほうが ImageMagick よりも処理速度が速いので、
libvip になくて ImageMagick にある機能を利用したい場合以外は
libvips を採用するのをオススメします。

```
% brew install vips
% brew install imagemagick
```

# Gitのインストール

ソースコード管理ツールの定番Gitをインストールします。

```
% brew install git
```

# データベースのインストール

PostgresSQLとMySQLをインストールします。

PostgreSQLはインストール時のmacOSのログインユーザーがスーパーユーザーに
設定されていますが、ログインユーザーでPostgreSQLを操作するのはよくない
ので、操作用のユーザーpostgresを作成し、スーパーユーザー権限を与えて、
postgresユーザーでPostgreSQL操作できるようにしておきます。

PostgresSQLのデータの格納場所のパスを.zhrc(シェルがzshの場合)に追加し、
シェルに反映後、PostgresSQLのデータベース・クラスタを作成します。

MySQLは、インストール直後、rootユーザー(スーパーユーザー)にパスワードが
設定されていないので、mysql_secure_installationを叩いて、セキュリティ
を強化しておきましょう。

```
% brew install postgresql@16
% brew services start postgresql@16
% psql -U postgres
postgres=# ALTER ROLE postgres WITH PASSWORD 'パスワード';
postgres=# \q
% brew services stop postgresql@16
% vi ~/.zshrc
export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"
export PGDATA="$HOMEBREW_REPOSITORY/var/postgresql@16"
% source ~/.zshrc
% rm -rf $(brew --prefix)/var/postgres@16
% initdb -U postgres --encoding=UTF-8 --locale=ja_JP.UTF-8
% brew services start postgresql@16
% brew services list
% brew services stop postgresql@16
% brew install libpq
% brew install mysql # mysql@5.7 (MySQL=5.7)
% brew services start mysql
% mysql_secure_installation
% brew services stop mysql
```

# Dockerのインストール (おまけ)

Ruby on Rails採用の開発プロジェクトで、開発・実行環境の構築にDockerを
利用していることがあります。

# 最後に

M1 Mac上でのRuby on Rails開発環境に最低限必要と考えられるモノの
インストール手順は以上です。

あとは、個々の環境で必要なモノをインストールして、開発環境をカスタマイズ
していきましょう。