更新日:
【Rails】 結局bundlerって何?bundlerの仕組みを図解形式で徹底解説
bundlerとは、gemのバージョンやgemの依存関係を管理してくれるgemです。bundlerを使うことで、複数人での開発やgemのバージョンが上がってもエラーを起こさずに開発できます。
以下のコマンドで、アプリにbundlerをインストールすることができます。
1
gem install 'bundler', 'バージョン'
bundlerが入ったかどうか確認するには、bundler -v
というコマンドで確認できます。
1
2
bundler -v
Bundler version 2.0.2
bundlerについて
この章では、bundlerの特徴やなぜbundlerが必要なのか仕組みについても1つ1つ解説します。
bundlerの特徴
bundlerとは、gemをどのバージョンで使うか一元管理できるgemです。bundlerを使うとこんなことができます。
bundlerを使ってgemをインストールするとgem同士の互換性を保ってくれるので、gemを追加したり時間が経ってもエラーを起こさず開発できる
Gmfileという1つのファイルにgemを書くのでgemの管理がしやすい
Gemfileを使ってアプリごとにgemを管理できる
環境ごとにインストールするgemを管理できる。
gemの互換性を保ってくれるので、Gemfileさえ共有すれば複数人でアプリを開発してもエラーを起こさない
色々便利な事が出来そうなbundlerですが、その前にたびたび登場するgemについて簡単に説明します。
gemとは
gemとはライブラリのことですね。ライブラリとは、便利で使い勝手の良いプログラムのコードが集まってるモノってイメージです。
例えばページネーションの機能を作りたいとします。7人のユーザー全てを今一覧で出してますが、これを1ページに3人ずつ表示するようにページネーションで実装していきます。
そうするとpaginationのコードを書いたり、paginationに合わせてデータを取得するコードを書いたりと
自作するとなると結構大変です。。
ただkaminariというgem(ライブラリ)を使えば、gem install 'kaminari'とするだけで
1ページごとに三人のユーザーを表示する機能が簡単に作れます。
このように自作すると大変で難しい機能がgemを使うとコマンド1つで簡単に作ることができます。
ページネーションの使い方を詳しく知りたい方は、
ページネーションの使い方を徹底解説を参照してください。
このページネーション以外にも様々なgemがあります。
ログイン機能を簡単に作れる機能(devise gem)
プログラムの動作を指定した場所で止めてdebugできる機能(pry gem)
いろいろなアイコンを簡単に表示できる機能(fontawesome gem)
1
<%= fa_stacked_icon("square-o", base: "twitter") %>
このように自作するのは大変な機能もgemを使うと簡単に機能を作成できます。
そして前述したようにbundlerもgemのバージョンやgemの依存関係を管理してくれるgemになります。
↑の説明だけではbundlerというgemがどの様なgemかよく分からないと思うので、bundlerがアプリの中でどの様な役割をしているか詳しく説明していきます。
bundlerの役割
Bundler makes sure Ruby applications run the same code on every machine.
Bundlerのgithubに書かれている説明です。こちら訳すと、bundlerは全てのマシーン(railsを動かすサーバー)でアプリケーションが必ず同じrubyのコードで動く様にさせることです。
全てのマシーンというのは、開発に参加しているエンジニアのPCであったり、本番サーバーで動いているサーバーであったり、その他にもアプリケーションを動かすマシーンがあればその全てです。
bundlerが必要な理由は、bundlerが出来る以前の事を知る必要があります。
Bundlerができる前の世界
Ruby On Railsは複数のgemから構成されたフレームワークで、gemのインストールなどを簡潔にするためにパッケージ管理システムを導入しました。そのgemのパッケージ管理システムがRubyGemsです。RubyGemsを使ってgemをインストールすることができます。
この動画ではkaminariというgemをインストールしてますが、このkaminariはどこからインストールしているかというと、rubygems.orgというRubyコミュニティのGemホスティングサービスからインストールされます。
このrubygems.orgからgemを検索したり今人気のgemを確認できます。gemをここからローカルにインストールしてアプリにgemを入れることができる様になったのですが、ここで大きな問題が起きました。大きな問題とは
- 急にアプリケーションが動かなくなる
- 自分の環境ではアプリは動いているのに、開発メンバーのアプリでは動かなくなる
なぜこの様な問題が起きたかというと、インストールしていたgemに依存しているgemのバージョンがupdateされて、互換性が無くなったからです。gemはより便利にするためにupdateが繰り返されることがあります。
自分がインストールしたときはうまく動いていたが、別の人が開発に加わりgemを自分と同じバージョンでインストールしたときに、依存gemのバージョンがupdateされたことで今まで動いていた自分の環境とは異なり、急に動かなくなることがありました。下記の画像の様なイメージです。
下記の画像はbootstrap-sassというgemを3.4.1でインストールしたとき、一年後開発に参加したBさんが同じgemをインストールしても依存gemのバージョンが上がっていてアプリが動かなくなるという例です。
この様な事態を防ぐためには、gemをインストールしたときにこのアプリケーションにはどのgemのバージョンを使って、そして依存gemのバージョンに関しても何を使ったかしっかりgemのバージョンを管理する必要がありました。
そのgemを管理するgemがbundlerになります。
今までgemをインストールするときにインストールするPCによってgemのバージョンが異なっていたのが、bundlerができたことによって、アプリを利用する全てのPCに同じversionのgem(依存するgemも含めて)をインストールすることが出来る様になりました。
bundlerを使ってgemをインストールするイメージ図が下記になります。
上記の画像の様にインストールしたgemとそのgemに依存するgemも、bundlerを通してしっかり結びつけることによって、アプリを利用する全ての人が依存するgemも含めて同じ環境でアプリを動作させることができる様になりました。bundlerの導入の背景、なぜbundlerが必要になったかはわかったと思います。
具体的なインストール方法については後述します。
とりあえずここでは、bundlerとはインストールしたgem・依存するgemのバージョンをしっかり結び付けていることで、アプリを動作させている全てのマシーンで同じrubyのコードで動作できると覚えておきましょう。
bundlerの役割については分かったと思うので、次はbundlerのインストール方法を見ていきましょう。
bundlerのインストール方法
bundlerをインストールする方法は下記になります。
1
gem install 'bundler', 'バージョン'
このコマンドでアプリにbundlerをインストールすることができます。
アプリでgemをインストールするときはbundle installというコマンド(詳しく後述します)を基本的に使いますが、
bundlerだけはRubyGemsのコマンドである gem installを使います。
理由としては、bundle installというのはbundler gemが入っていないと使えないコマンドなので、bundlerだけはgem installで入れる必要があるためです。
bundlerが入ったかどうか確認するには、bundler -vというコマンドで確認できます。
1
2
bundler -v
Bundler version 2.0.2
GemfileとGemfile.lockの違い
Bundlerというgemによってrubygems.orgからインストールしたgemの依存関係を考慮して、うまいことRailsアプリにインストールしてくれていることが分かりました。
では次は、bundlerがどうやってアプリに必要なgemをインストールするか、そして依存関係を考慮してどの様にgemのバージョン管理をしているか理解していきましょう。
bundlerがgemの管理をするには、下記の2つのファイル(Gemfile・Gemfile.lock)が必要になるので、その説明をしていきます。
- Gemfile
- Gemfile.lock
Gemfileとは
Gemfileとは、簡単にいうとRailsアプリで利用するgemの一覧が載っているファイルのことです。例えばこのファイルを見たときにdeviseと書いてあれば、このアプリのログインはdeviseで作っているんだなと分かったりします。
pikawakaのGemfileを参考に説明していきます。
上の画像にある通り、Gemfileはアプリケーションディレクトリの直下になければなりません。
そして画像の様にgemとバージョン名を記載すると、記載されたgemがpikawakaのサイトの中で使用することができます。もしバージョンの指定がなければ、最新のバージョンがインストールされることになります。
1
2
3
4
5
# バージョン指定した場合
gem 'gem名', 'バージョン'
# バージョン指定しなかった場合
gem 'gem名'
pikawakaはこのGemfileを参照して、pikawakaで使用するgemをインストールします。
Gemfile.lockとは
Gemfile.lockとは、railsアプリで利用するバージョンも含めた全てのgemの一覧が載っているファイルで、アプリで利用するgemのバージョンをlockしているファイルになります。
下記の画像を見てみましょう。
画像を見ると、先ほどの画像のGemfileに記述されたbootsrap-sassが3.3よりも上のバージョンでインストールする様に記載されていたので、Gemfile.lockにはbootstrap-sassが3.4.1でインストールされたことがわかると思います。
1
gem 'bootstrap-sass', '~> 3.3'
そしてこのbootstrap-sassを使うためにはautoprefixer-railsというgemとsasscというgemが必要になるので、bundlerがpikawakaのアプリが動く様にバージョンを調整して依存しているgemも自動でインストールしてくれました。
なぜGemfile.lockに依存関係のgemのバージョンまで書かれているかというと、bundlerが依存関係のあるgemやバージョンも含めてしっかりどのバージョンのどのgemを使うか記載がなければ、最初は動いても後々動かなくなるということがあるからです。
例えば、pikawakaには運営者以外に二人開発メンバーがいるのですが、彼らのPCでbootstrap-sassをインストールしたときにその依存しているgemのバージョンがupdate(時間が経ったのでバージョンがupdateされている)されている可能性が大いにあります。
そうなると、私の環境であればpikawakaの〇〇の機能は動いていたのに、彼らのPCだと〇〇の機能が正常に動かなくなるといった事態が起こる可能性があります。なぜかというと、インストールしたgemのバージョンが違うので開発環境が異なっているからです。
この様にインストールしたgemのバージョンの違いによって、開発環境が異なるのを防ぐために、インストールしたgemのバージョンやgemのバージョンを変更されない様にlockする必要があります。だから、Gemfile.lockというファイル名なのです。
つまり、GemfileとGemfile.lockの違いをまとめると
Gemfile | Gemfile.lock | |
---|---|---|
内容 | アプリで使用するgem | 使用するgemと依存関係のあるgem |
状態 | インストール予定のgem | インストールされたあとのgem |
ヴァージョン |
gemのバージョンを指定できる、 もし指定しなければ最新のgemのバージョンがインストールされる |
インストールされたgemと 依存関係のあるgemのバージョンが記載されている |
場所 | アプリケーションディレクトリ直下 | アプリケーションディレクトリ直下 |
方法 | 手動で記述 | 自動で作成される |
この様になります。GemfileとGemfile.lockがbundlerでどの様な役割をしているか分かったと思います。
そして次の説明では、bundlerを使ってgemをインストールする方法について解説していきます。これまでgemをインストールと何度も記述していましたが、どうやってインストールできるか?、インストールしたファイルはどこに保存されるかみていきましょう。
bundle installと bundle updateの違い
railsアプリにgemをインストールする方法は、下記の2つのコマンドです。
- bundle install
- bundle update
この2つを使えば、gemをrailsアプリに取り込むことができますが、gemのインストールのされ方は異なります。
この違いを理解していなければ、バグが発生してアプリが動かなくなることもあるので、2つのコマンドの違いを理解しましょう。
bundle installとは
bundle installとは、bundlerを使ってGemfileからgemをインストールするコマンドです。
bundle installで実行することは以下の3つです。
- Gemfile.lockでどのgemがinstallされているか確認する
- Gemfile.lockを確認した後にGemfileに記述されているgemを確認する
- Gemfile.lockにないgemをGemfileから見つけた場合、そのgemをインストールする。
Gemfile.lockにないgemをGemfileから見つけた場合は、そのgemをrubygems.orgからインストールするので、Gemfileにある全てのgemがすでにGemfile.lockに記述されていれば読み込むものはない為、すぐにbundle installは実行終了します。
上記の動画のbundle installの実行が早いのはGemfileに新しく追記したgemがないから早く終了しました。
ネットワーク環境にもよりますが、1からgemを読み込む場合は多少は時間がかかります。
bundle installでinstallしたgemはどこにinstallされる?
bundle installでinstallされたgemはどこに入っているのでしょうか?
bundle installされたgemはデフォルトでは
~/.rbenv/versions/projectのrubyバージョン/lib/ruby/gems/projectのrubyバージョン(x.x.0)/gemsになります。
projectのrubyバージョンとは、rubyのどのバージョンでアプリが動いているかということですね!
pikawakaの場合だとrubyのバージョンは2.4.1になります。
rubyのバージョンが2.4.1の場合だとpikawakaでinstallしたgemは、~/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0(x.x.0)/gemsにbundle installしたgemは保存されます。(x.x.0)とはどういうことかというと、2.4.1ならばrubyは2.4系のバージョンとなり、2.4.0のディレクトリに保存されます。これが例えばpikawakaのrubyのバージョンが2.5.3だとすると、保存先は~/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0(x.x.0)/gems
になるということです。
ここの保存先をみてみると、やたらとたくさんのバージョンがあります。
ここでは、pikawakaで入れたgem以外にも沢山のgemが格納されています。2.4系のアプリでinstallしたgemは全てここに入るためです。 アプリで使ってるgemのソースをみたい時にバージョンをGemfile.lockから調べてそのgemのバージョンのフォルダを~/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0(x.x.0)/gems
から探して開くのは正直面倒です。
そんな時、アプリで使っているgemはアプリのフォルダの中に入れられたら管理もし易くて便利だと思いませんか?
なんとbundle installの--pathオプションを使えば、installするディレクトリを指定できます。よくある指定場所が下記です。
1
bundle install --path vendor/bundle
vendor/bundleに保存先を指定すれば、railsアプリの直下のvendor/bundleディレクトリにインストールされ、railsアプリケーションの中だけにインストールされます。
pikawakaの場合だとpikawaka/vendor/bundleに保存されます。
初めのinstallでGemfileのgemを全て読み込むので、installに時間がかかりますね。
gemを全てインストールし終えるとbundlerでinstallしたgemがvendor/bundleに保存されたことが分かります。
2回目以降はbundle installだけで新しく追加されたgemはvendor/bundleに自動的に入る様になります。
1
2
pwd
/Users/yuya/Desktop/pikawaka_dir/pikawaka/vendor/bundle/ruby/2.4.0/gems
bundle installの説明を最後にまとめると
bundle updateとは
bundle updateとはGemfile.lockに書かれている内容は無視し、Gemfileに書かれているgemを全てインストールするコマンドです。
bundle updateの特徴は、Gemfile.lockの内容を見ずにGemfileに書かれているgemをupdateすることです。
updateできるgemがあればGemfile.lockのバージョンをupdateします。
bundle updateして、pikawakaのGemfile.lockの記述がどう変わったか見てみましょう。
この様に少しだけバージョンがupdateしていることが分かります。bundle updateはGemfileに記載されている全てのgemに対して行われるので、このupdateにより今まで動いてたアプリケーションが急に動かなくなる可能性もあります
また、bundle updateをしてGemfile.lockを更新してそれをgitであげると、開発メンバーがそれをpullして動かなくなる可能性もあります。ですからbundle updateコマンドは慎重に使い、基本的にはbundle installだけを使う様にしましょう。
bundle update rails
そんな使うとちょっと危険な感じのbundle updateですが、bundle updateは単体のgemをupdateしたい時に使うことがよくあります。bundle updateをしてしまうと全てのGemfileに書かれているgemをupdateしようとするので危険ですが、updateしたいgemだけに絞ってupdateするとアプリの影響も少ないですしね。
そんなbundle updateを単体で指定してgemのバージョンを上げる方法は
1
bundle update gem名
これで指定したgemのバージョンをupdateすることができます。
今使ってるprojectのrailsのバージョンを最新にしたいといった大掛かりなアプリのアップデートをするときは
bundle update railsというコマンドを使います。アプリのrailsのバージョンを上げたい時に使うコマンドです。
bundle exec
bundle exec コマンドについて説明していきます。よくbundle execコマンドがどういう動作をしているか分からない、おまじない的な感じでとりあえずbundle execコマンドを使っておいた方が良い!と言われたから何をやってるかわからないけど、とりあえず付けているという話を聞くことがあります。
そんなちょっと謎の多いおまじない的な感じで使ってるbundle execコマンドですが、この章でなぜbundle execが必要なのか徹底解説します!
bundle execが必要な理由
bundle execコマンドとは、アプリのGemfile.lockに記載されているgemを使用するコマンドです。
またpikawakaのbootstrap-sassのgemを参考例に説明していきます。
bundle installでpathオプションを指定しなかった場合、~/.rbenv/versions/projectのrubyバージョン/lib/ruby/gems/projectのrubyバージョン(x.x.0)/gems
にgemが保存されると言いました。
pikawakaのrubyのバージョンは2.4.1なので、~/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0(x.x.0)/gems
にbootstrap-sassが保存されてます。本当にあるかどうかlsコマンドで見ていきましょう。
1
2
3
4
5
ls ~/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems | grep bootstrap-sass
bootstrap-sass-3.3.7
bootstrap-sass-3.4.0
bootstrap-sass-3.4.1
lsコマンドを打つと3つのgemが出てきました。3つ出てきた理由としまして、このディレクトリに入っているgemは、railsアプリが2.4系でインストールしたgemが全て入っているのでpikawaka以外のプロジェクトでインストールしたgemも入っているためです。そしてpikawakaで使用しているbootstrap-sassのバージョンは3.4.1になります。
このとき、bootstrap-sassがGemfile.lockに3.4.1と書かれているので、bundle execと付けると~/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bootstrap-sass-3.4.1
が読み込まれます。
ちょうど下記の様なイメージ図です。
この様にbundle execを付けることで、railsアプリでインストールしたgemを指定して使うことができます。
もしbundle execコマンドを使用しなければシステム共通のライブラリ保存場所を環境下にしてコマンドが実行されるので、bundle installでinstallしたgemのバージョンでないgemを使用してアプリが動かない可能性があります。
つまりbundle execコマンドは必ずつけた方が良いと言われる理由は、アプリでbundle installしたgemを使うためということですね!
またbundle install --path vendor/bundleを指定した場合も同じで、bundle execコマンドを使うとpikawakaでbundle installした保存先のpikawaka/vendor/bundle/ruby/2.4.0/gems/以下のgemファイルを使用します。
bundle execコマンドを使用すると、Gemfile.lockに書かれているgemを使用すると覚えておいてください!
Railsについて曖昧な理解になっている方は、こちらの書籍を参考にすると情報を結びつけて整理することができます!「Ruby on Rails チュートリアル」を完走したくらいの方へ推奨します。
bundle コマンド
bundle exec以外にも便利なコマンドがたくさんあるので、どんなコマンドがあるか見ていきましょう
bundle init
こちらはGemfileを作るコマンドです。railsならデフォルトで出来ているので、あまり使う機会はなさそうです。
1
2
3
4
5
6
7
8
9
10
11
12
bundle init # Gemfileが作成される
# 以下作られたGemfile
-------------------------------
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
# gem "rails"
bundle list
既にインストールしているgemパッケージの一覧を表示するコマンドです。
1
2
3
4
5
6
7
8
9
10
bundle list
* CFPropertyList (2.3.6)
* actioncable (5.2.3)
* actionmailer (5.2.3)
* actionpack (5.2.3)
* actionview (5.2.3)
* activejob (5.2.3)
* activemodel (5.2.3)
...
bundle package
bundle packageは、vendor/cacheディレクトリに.gemファイルをコピーするコマンドです。Bundlerはrubygems.orgよりも、cache(キャッシュ)されたvendor/cacheディレクトリのGemを優先します。
1
bundle package
bundle config
全てのBundler設定を表示するコマンドです。
またoptionを渡せば、Bundlerの設定もできるコマンドになります。
1
2
bundle config # Bundler設定を表示
bundle config <name> <value> # Bundler設定をするコマンド
bundle clean
ローカルのbundle install先の使われていないGemを綺麗に削除してくれるコマンドです。
1
2
3
4
5
6
7
bundle clean
Removing parallel (1.19.1)
Removing activestorage (5.2.4)
Removing image_processing (1.9.3)
Removing actionpack (5.2.4)
...
bundle open
オプションで指定したgemファイルを開くコマンドです。アプリに入れたgemがどの様な挙動をしているかgemのファイルの中身を調べたいときにこのコマンドがあれば簡単にgemを開けるので、便利です。
1
bundle open gem名
bundle show
bundle show gem名を指定するとそのgemがどこに保存されているかみることができます。
パスが分かればどこにファイルがあるか探す必要もなく、ファイルを開くのも簡単なので便利なコマンドです。
1
2
bundle show bootstrap-sass
/Users/yuya/Desktop/pikawaka_dir/pikawaka/vendor/bundle/ruby/2.4.0/gems/bootstrap-sass-3.4.1
bundle viz
gemの相関図を画像で出してくれるコマンドです。
1
2
3
4
brew install graphviz # こちらをinstallする必要があるのでinstallします。
gem i ruby-graphviz # こちらをinstallする必要があるのでinstallします。
bundle viz -v # これで画像でgemの相関図を保存
一部抜粋
まだ紹介していないコマンドがあるくらい、bundlerには沢山のコマンドがあります。普段使わないコマンドも沢山あったと思うのですが、知ってるだけで作業が楽になったりする便利なコマンドなので、ぜひこの記事を読んで自分のアプリに役立ててください。
bundlerの設定
bundlerの設定ファイルについて解説します。
アプリケーションごとに.bundle/configファイル(設定ファイル)を作成できます。
この設定ファイルを使うとbundlerでいろいろ便利な設定ができます。
例えば、bundle install --path vendor/bundleと打つと、2回目以降はbundle installだけで新しく追加されたgemはvendor/bundleに自動的に入る様になったと言いましたが、それはなぜかというと
configファイルにBUNDLE_PATH: "vendor/bundle"と記載されているからです。
1
2
3
4
cat .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
このBUNDLE_PATH以外にも便利な設定があるので、紹介します。
BUNDLE_FROZEN
bundle install --deploymentというコマンドを打つと、自動的にBUNDLE_FROZEN: 1というオプションがつきます。このオプションがつくことで、Gemfile.lockを元にgemのインストールを行うようになります。
このオプションを解除するには、configファイルからBUNDLE_FROZEN: 1の行を削除する必要があります。
BUNDLE_WITHOUT
test環境以外にbundle installを実行したかったり、環境によってbundle installするのを除外したいケースがあったとします。そんなときはbundle install --without testというオプションをつけて実行するとBUNDLE_WITHOUT: testとconfigファイルに追加され、test環境には適用されない様になります。
これを解除するのも.bundle/configで指定された行を削除すれば完了です。
この記事のまとめ
- bundlerとは、gemをどのバージョンで使うか一元管理できるgemのこと
- インストールしたgem・依存するgemのバージョンをGemfile.lockに記載することで、どの環境でも同じrubyのコードで動かすことができる
- bundlerにはよく使うbundle install以外にも便利なコマンドが沢山あるので、ぜひいろんなコマンドを使ってbundlerを今よりもっと使いこなそう!