Gemfile?bundler?Rails開発するなら理解しておきたいgem管理の基礎知識

Ruby

こんにちは。Enjoy IT Life管理人の仁科(@nishina555)です。

Ruby on Railsは直感的にコードを記述できる、プログラミング初心者にもオススメのフレームワークです。

Ruby on Railsを利用すれば、開発者が細かいことを気にしなくてもフレームワーク側でよしなに実装をしてくれるため、簡単にWebアプリケーションを作ることができます。

一方で、便利なフレームワークであるがゆえにRuby on Railsの仕組みについてきちんと知る機会も少ないと思います。

そこで今回は、Ruby on RailsでWebアプリケーション(以降ではRailsアプリと略します)を開発するうえで理解をしておきたい、Ruby on Railsに関する仕組み・基礎知識について図をまじえながら解説をしていきたいと思います。

Ruby on Railsで知っておくべきことはたくさんありますが、その中でも特にbundler、Gemfile、Gemfile.lockといったgemに関するはなしを今回はしたいと思います。

このように思っている方の参考になればと思います。↓

  • Railsの参考書によく出てくる「bundle install」ってなにをしてるの?
  • GemfileとGemfile.lockって似てるけど違いがあるの?
  • Railsアプリだとgemってどうやって管理されているの?

Railsアプリの全体像

はじめに、Railsアプリがどういったファイル・ディレクトリで構成されているのかについて紹介したいと思います。

以下に、はじめてRailsアプリを立ち上げる時のディレクトリ構造を記載しました。なお、簡略化するため細かい情報は省略しております。

Rubyのバージョンは2.5.3、bundlerのバージョンは2.0.1となっております。

.
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── app
├── bin
├── config
├── config.ru
├── db
├── lib
├── log
├── package.json
├── public
├── storage
├── test
├── tmp
└── vendor/bundle
      └── ruby/2.5.0
            ├── bin
            ├── build_info
            ├── cache
            ├── doc
            ├── extensions
            ├── gems
            └── specifications

上記の構成について簡単に解説をします。

図を見てわかるように、Railsアプリではルートディレクトリ(一番上の階層)に『Gemfile』『Gemfile.lock』が存在します。

そして、Railsアプリによっては図のようにvender/bundleというディレクトリが用意されており、その配下に『gem』が配置されています。(『Railsアプリによっては』という表現をしている理由については後述します。)

『gem』はRubyのライブラリのこと。便利な機能がパッケージ化されている

gemはRubyGemsと呼ばれるRuby用のパッケージ管理システムによって管理されたライブラリです。RubyGemsが提供するgemコマンドを通じてインストール等ができます。

gemを利用することでゼロから実装をしなくても簡単に便利な機能を取り入れることが可能になります。

Railsアプリで使われる有名なgemには、ログイン機能を提供するdevise、検索機能を提供するransackなどがあります。

冒頭で『Ruby on Railsは直感的にコードを書くことができるフレームワーク』と紹介しましたが、簡単にRailsアプリが作れるのも豊富にある便利なgemたちのおかげです。

ぼくはRailsエンジニアとして仕事をしていますが、実際の開発の現場では「xxxのgemを新しく追加しました」とか「xxxのgemに脆弱性が見つかったのでgemのバージョンをアップデートしました」1といった会話が行われています。

『bundler』は依存関係にあるgemの依存関係やバージョンを管理してくれるgemのこと

Railsアプリを開発する上で大事になってくるのがbundlerというgemです。
bundlerは『gem同士の依存関係やgemのバージョンを管理する』gemです。

先ほど紹介したように、gemを活用することでRailsアプリを効率良く開発することができます。
しかし、インストールしようとしているgem自身もほかのgemを利用しているケースがあります。その場合、依存関係にあるgemもあわせてインストールする必要があります。

また、各gemにはバージョンが設定されているのですが、同じgemでもバージョンが異なるとRailsアプリの挙動を変えてしまったり、他のgemに影響を与えてバグを発生させたりする可能性があります。

これらの問題を解決してくれるのがbundlerです。
bundlerを利用することで『依存関係にあるgemの一括インストール』『gemのバージョン管理』ができるようになります。

実際にRailsアプリを実装する際にはたくさんのgemを利用することになるわけですが、bundlerを活用することできちんと互換性を保ちつつ、Railsアプリで利用するgemを一元管理することができます。

bundlerではbundleコマンドが提供されており、bundleコマンド経由でgemの管理をすることになります。
Ruby on Railsの参考書によくある『bundle install』というコマンドは『bundlerを利用してgemをインストールする』という意味になります。

bundleコマンドの詳細については『意外とよくわかっていないbundlerについて』で紹介していますので、興味のある方はご覧になってください。

意外とよくわかっていないbundlerについて

bundlerでgemをインストールする際はオプションを利用することでgemのインストール先を指定することができます。
例えばbundle install --path vender/bundleと実行すれば、vender/bundle配下にgemがインストールされます。
慣習としてbundle installのパスをvender/bundleにすることが多いのですが、インストール先は意の場所に設定できます。

記事の冒頭で『Railsアプリによってはvender/bundleというディレクトリが用意されており…』という表現を用いた理由も、gemのインストール先は任意のディレクトリに指定できるからです。

『Gemfile』とはRailsアプリで利用するgemの一覧を管理するファイル

bundlerを利用することでgemの依存関係やバージョンを管理することができるようになります。Railsアプリを実装する場合は多くのgemを利用するので、bundlerの利用は必須です。

では、『bundlerによってインストールされるgemはどこで管理されているのでしょうか?
それが今から紹介するGemfileの役割です。

冒頭でも紹介をしましたが、GemfileはRailsアプリのルートディレクトリに存在しています。bundlerはGemfileの内容をもとにgemのインストールを行います。

具体的にはbundle installというコマンドでgemをインストールするのですが、その際にはGemfileに記載されているgemの一覧を参照し、まだインストールされていないgemがあればインストールを行います。

すでにgemがインストールされていた場合でもGemfile.lockに記載されているバージョンと差異がある場合は改めて当該gemをインストールします。

ですので、Railsアプリで新しくgemを追加したいという場合はGemfileにgemの名前を追記していくことになります。

インストールの際はGemfileに記載されているgemに加え、対象のgemと依存関係にあるgemも合わせてインストールされます。

例えば、Gemfileにgem railsと記載されていればrailsがインストールされます。
railsが提供している機能の1つにactioncableというものがあるのですが、2bundle installを実行すると、actioncableの記載がGemfileになくてもrailsと合わせてactioncableも同時にインストールされます。

Gemfile、bundleコマンド、gemの関係性および処理の流れを図で表現すると以下のようになります。

Railsアプリで利用するgemはbundlerで管理されており、そのbundlerはGemfileを参照しています。
つまり、GemfileにはRailsアプリで利用されているgemの一覧が記載されているということになります。

bundlerでgemを管理する場合に利用されるのがGemfileなので、Railsアプリ開発環境下以外でもGemfileを利用することは可能です。

『Gemfile.lock』はGemfileをもとに実際にインストールされたgemの一覧とバージョンが記載されたファイル

bundlerはGemfileの内容をもとにgemのインストールを行います。

先ほど説明したように、bundlerはインストール対象のgemだけでなく、そのgemと依存関係にあるgemも合わせてインストールしてくれます。

Gemfile.lockには依存関係にあるgemも含め、bundlerによってインストールされた全てのgemとそのgemのバージョンが記載されています。

Gemfile.lockはGemfileをもとにbundlerによってインストールされたgemの結果を出力するファイルです。そのため、基本的には手動で更新することはありません。
bundle installもしくはbundle updateをすることでGemfile.lockは自動で更新されます。

先ほど、Gemfileにgem railsと記載されているとrailsおよびrailsが依存するactioncableがインストールされるという例を紹介しました。

Gemfile.lockには実際にインストールされたrailsやactioncableをはじめとするgemの一覧が記載されます。
そして、どのバージョンのgemがインストールされたかという情報もあわせて記載されています。

Railsアプリにインストールされたgemと、Gemfile.lockの関係性を図で表現すると以下のようになります。

GemfileとGemfile.lockの関係性は?違いは?

GemfileとGemfile.lockの違いについて表にすると以下のようになります。

Gemfile Gemfile.lock
記載されているgem bundlerでインストールするgem bundlerでインストールしたgem
更新タイミング bundleコマンド実行前 bundleコマンド実行後
更新方法 手動更新 自動更新

『Gemfileの内容をもとにbundlerがgemをインストール → インストールしたgemの結果をGemfile.lockに記載』という一連の流れを図としてまとめると以下のようになります。

Gemfile、Gemfile.lockの違いについては『【初心者向け】GemfileとGemfile.lockの違い』でも紹介していますので、興味のある方はご覧になってください。

【初心者向け】GemfileとGemfile.lockの違い

まとめ: Railsアプリを作る前にgemの管理方法については理解をしておこう

Railsアプリの開発をおこなっていくにあたり『gemを追加してbundle installを実行する』という機会に多く出会うと思います。

gemを利用することでRailsアプリ開発を効率よく進めることができますので、gemの管理方法についてはきちんと理解をしておきましょう。

今回のまとめ
  • gemは便利な機能がパッケージ化されたRubyのライブラリのこと
  • bundlerを利用することで『依存関係にあるgemの一括インストール』『gemのバージョン管理』が可能になる
  • Gemfileはbundlerがgemをインストールする際に参照するファイルのこと
  • Gemfile.lockはbundlerによってインストールされたgemおよびそのバージョンが記載されたファイルのこと

この記事がいいなと思いましたらツイッター(@nishina555)のフォローもよろしくお願いします!


  1. bundler-auditと呼ばれる『gemの脆弱性を検知する』というgemもあります。 
  2. Ruby on Rails5系以降の場合。