Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Ruby 歴 10 年の私が【絶対に】 gem install rails コマンドを実行しない理由

タイトルは釣りです。

主語が大きすぎてちょっとドキドキしてます。では、タイトル通りの話をしていきます。

結論

  • 結論から言うと、 Ruby の環境が 汚れる からです
  • gem install xxx コマンドは基本的に Ruby の環境にインストールされることになります
    • ですので、Ruby が状態を持つことになり、冪等性(べきとうせい)に欠けてしまいます
  • bundler という便利な仕組みがある上では、 gem install xxx を実行するシチュエーションは限定的になると思います
  • gem installbundle install コマンドを使った時に何が起きているかを意識しましょう

開発環境構築のジレンマ

開発環境を構築するにあたって、いろんな方法があります。

画一された手段がないというのはメリットでもあり、デメリットでもあります。 (自由性という意味で)

ですが「よくわからないけど、Qiita に載っていて、それが上手くいったからその手順でいいや」というのは問題です。

OSS で公開されているソフトウェアは用途に特化した形で公開されています。それを上手く活用する方法を自分なりに示したいと思います。

具体例

例えば、こういった記事があります

(Ubuntu)Ruby on rails 6.0 環境構築

注意点ですが、 この記事が悪いということではなく、こういった手順を私は踏まない という話なだけです。

じゃぁ、貴方はどうやるの?

私は Rails プロジェクトを構築する際には以下のような手順を踏みます。まずは概要を示してから、具体的なコマンドを書いていきます

  1. Ruby をビルドするのに必要なパッケージ(ライブラリなど)を事前にインストールする
  2. rbenv を利用して Ruby をインストールする
  3. Rails 6 以降で必要になった Node.js をインストールする
  4. プロジェクトのためのディレクトリを適当な名前で作成する (example_project)
  5. プロジェクトディレクトリ配下で bundle init コマンドを実行し、 Gemfile ファイルを作成する
  6. 作成した Gemfile ファイルを編集して gem 'rails' となっている行を有効に(コメントイン)する
  7. bundle install --path=vendor/bundle を実行して、特定のパス配下に gem をインストールする
  8. rails s コマンドで立ち上げる

では、具体的なコマンドを書いていきます。
環境は Ubuntu Linux を前提とします。

Ruby が無い状態から開始します。ほぼほぼ「(Ubuntu)Ruby on rails 6.0 環境構築」と同一ですが、順番が異なります。

前準備

# apt パッケージの情報を最新にする
sudo apt update -y
# Ubuntu にインストールされているソフトウェアを最新にする
sudo apt upgrade -y
# Ruby のビルドに必要なパッケージを apt 経由でインストールする
sudo apt install build-essential -y
sudo apt install -y libssl-dev libreadline-dev zlib1g-dev

# sqlite3 を利用する場合、sqlite3 に関するライブラリをインストールしておく
sudo apt install libsqlite3-dev

# PostgreSQL の場合には下記コマンドを実行
sudo apt-get install postgresql-common
sudo apt-get install libpq-dev

# MySQL or MariaDB の場合には下記コマンドを実行
sudo apt-get install libmysqlclient-dev

Rubyをインストール

# rbenv(パッケージ管理ツール)をインストール
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
# 環境変数にPathを設定
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
# シェルを再起動
exec $SHELL -l

# ruby-buildをインストール
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

# Rubyをインストール
rbenv install 2.6.2
rbenv global 2.6.2

# bundler コマンドを gem としてインストールする
# Ruby 2.6 からは bundler が内包されるようになったので、下記の手順は不要です。 2.5 以前では必要です
gem install bundler

ここまでで Ubuntu Linux に ruby コマンドと gem コマンド、 bundler コマンドがインストールされた状態になりました。

Ruby on Rails で開発を始めるにはまだかかります。

ですが、この状態でしたら、 Ruby のプログラムを書き始める状態までは完了しています。

ここから手順が異なります

次に Rails 6 以降で必要になった Node.js をインストールします。

# node.js, npmをインストール
sudo apt install -y nodejs npm
# n packageをインストール
sudo npm install n -g
# n packageを使ってnodeをインストール
sudo n stable
# 最初に入れた古いnode.js, npmを削除
sudo apt purge -y nodejs npm
# 再ログイン
exec $SHELL -l
# yarn packageをインストール
sudo npm install yarn -g
# node.js のバージョンが最新か確認
node -v

この手順を経ることで、Ubuntu Linux 上に ruby (2.6.2) と gem コマンド、 nodeyarn コマンドがインストールされました。

ここで一息入れます。

これらの準備が整うことで Rails 6 を動かす前準備ができたことになります。

次に自分が作りたいプロジェクトのディレクトリを作成し、Rails のセットアップを行います

# 自分が作成するプロジェクトのディレクトリを作成
mkdir example_project
# 作成したディレクトリに移動
cd example_project

# bundle init を実行して Gemfile ファイルを作成
bundle init

# 作成された Gemfile を編集して「# gem 'rails'」の部分をコメントインする
# 「# gem "rails"」となっている箇所を#(シャープ)を消して「gem 'rails'」という形にする
gedit Gemfile

# rails をインストールするために bundle install
bundle install --path vendor/bundle

# rails new コマンドを実行して、rails に関する gem をまとめてインストールする
bundle exec rails new .
(ここで、「上書きしますか?」的な英文メッセージが表示されるので「Y」を入力)

これらの手順を踏むことで、 Rails が利用できるようになります。

bundle exec rails s

2020/07/18 追記

コメントでご指摘いただき、bundle install する際に --path vendor/bundle に関することについて述べておきます。
Bundler 2.1 以降、 --path オプションは deprecated(非推奨) となりました。この点に関しての対処はこちらに記載があるので参照をお願いします。

bundle install時に"[DEPRECATED] The --path flag is deprecated"という警告が発生した場合の対応手順

解説

どういう状態になったかを適宜解説していきます

まず、 「前準備」であるライブラリを入れた状態を図として示します

スクリーンショット 2020-07-17 22.48.57.png

これらは Linux 上にライブラリがインストールされた状態です。これだけでは、 Ruby コマンドの実行はできません (Ruby がインストールされていないので当たり前ではありますが)

「Rubyをインストール」の状態では、以下の状態になります

スクリーンショット 2020-07-17 23.01.28.png

「Ubuntu Linux にインストールされたパッケージ」のライブラリを元に ruby と gem コマンドがインストールされます。bundler コマンドがある理由は gem install bundler をコマンドで bundle コマンドをインストールしているからです。

次に「Node.js」をインストールした状態を示します。

スクリーンショット 2020-07-17 23.24.08.png

点線で示したのは sudo apt purge -y nodejs npm コマンドで削除しているためです。

この状態で ruby, gem, bundler, node, npm, yarn コマンドが実行できる状態です。

意識したいポイントとしては、Ruby に関して言えば ruby, gem, bundler コマンドのみ実行可能で、 JavaScript においては node, npm, yarn コマンドが実行できる状態である、というだけです。

次に「自分が作りたいプロジェクトのディレクトリを作成し、Rails のセットアップを行う」という状態を示します。

スクリーンショット 2020-07-17 23.36.13.png

はい、これで vendor/bundle に プロジェクトに必要なライブラリ がインストールされたことになります。

これだけだと対比が分かりづらいと思うので、gem install rails を実行したケースを示します。

スクリーンショット 2020-07-17 23.39.03.png

強調したいため赤字で示しました。

ここで言いたいこととしては、 rails コマンドを実行する rails の gem と 「vendor/bundle ディレクトリ以下 rails 関連の gem が格納される」のバージョンが異なる可能性がある ということです。

こういった状態は「ruby にインストールされている特定のバージョンの gem と vendor/bundle 以下にインストールされている gem のバージョンが一致しないことには、完全な再現はできない (冪等性(べきとうせい)がない)」という状況を生み出し得るということです。

一方、先述した方法(gem install rails を用いない方法) では、「Ubuntu Linux の HOME ディレクトリ以下に設置されたプログラム類」には依存しません。

ですので、 bundler コマンドを有効活用して、特定のディレクトリ配下にプログラムに必要なライブラリをインストールするようにし、「できる限り Ruby 標準の gem の環境はシンプルに保つ」ということをすると、快適な Ruby の生活ができると思います。

(とはいえ、このお話は恐らく、 Python などパッケージ管理システムを持っているエコシステムでは同じ話が適用できますが)

ですので、きちんと 各コマンドが何の役割を担当していて、どういったことに適するかの意味を理解して実行することが大切 だと思います。

勢いで書いているため、乱筆乱文お許しください。

蛇足

  • Ruby on Rails の環境を構築するのに、なんで Node.js をインストールしなきゃいけないんだ!という話
    • Rails 6 から webpacker というものが標準になりました
    • webpacker は node.js のエコシステムである yarn を利用することが必須になります
    • 一つの言語で完結しないのは微妙感がありますが、結局 JS 関連で悩むことになるよりも、Node.js のエコシステムに乗っかってしまった方が長期的に考えると幸せになる、ということだと個人的には解釈しています。
kaishuu0123
何をやる人なんだか一言で言いにくいので、結局「システムエンジニア」を名乗っています。(プログラミング/ネットワーク/インフラ etc ...)バックエンド寄りです。
https://www.saino.me/
weseek
WESEEK, Inc. はシステム開発のプロフェッショナル集団です。UIデザインからサービス運用のためのネットワーク・インフラ構築まで全てを自社で行います。
https://weseek.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away