Gemfileを非エンジニアが理解するまでの過程

#Gemfileってなぁに？
---
ご指摘いただき、Bundlerの内容を修正しました。

---
ポートフォリオ作成にあたり、あれこれ環境構築していました。

Gemfileってなんやねん。

チュートリアルではわからないままやっていたわけですが、ここいらでまとめておきたい。


Gemfileとはなんぞや ＼_ﾍﾍ(∀｀*)カタカタ

>『Gemfile』とはRailsアプリで利用するgemの一覧を管理するファイルです。
　[引用](https://qiita.com/nishina555/items/1b343d368c5ecec6aecf#:~:text=Gemfile%E3%81%A8%E3%81%AF,%E7%AE%A1%E7%90%86%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B%EF%BC%9F%E3%80%8F&text=%E3%81%A7%E3%81%99%E3%81%AE%E3%81%A7%E3%80%81Rails%E3%82%A2%E3%83%97%E3%83%AA%E3%81%A7,%E3%81%84%E3%81%8F%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82) 

gem...??

>gemとはrubyのライブラリのことです。
[引用](https://qiita.com/kamohicokamo/items/ded4cad5be1778547640)

・・・ライブラリ？？

>便利なプログラムの部品をいっぱい集めて、ひとまとめにしたファイルのこと
[引用](https://wa3.i-3-i.info/word1473.html)


・・・・芋づる式にわからない単語がでてくる。

#はじめに大枠を理解する

<strong>関連キーワード：　Gemfile, Gemfile.lock, bundler, ライブラリ, gem

上記のキーワードを、ストーリー化してまとめてみる。

---

<strong>ある男性がいます。奥様と子供２人の４人家族。奥様は日々家事に追われて疲れています。お父さんと子どもたちは「お母さんを手伝って楽をさせてあげよう」と画策します。

<strong>「お母さんを楽にしてあげる」という目的を立てました（アプリケーション）

<strong>そのための方法は色々あります、自分で考えてもいいし、書店（Gemfileにおけるsource）から色々な本（gem）を手に入れて着想を得てもいいです。

<strong>お父さんはどうやって目的を達成するか行動計画を立てます。（Gemfile）

```:Gemfile
[https://rubygems.org] という書店から「洗濯を手伝う方法 ver２．０」、「美味しい料理の作り方 ver３．５」
「奥様と作るアサーティブな関係 ver４．０」、「お母さんの機嫌を取るための方法 5選 ver１．１」を入手しよう
```

<strong>その設計図を元にお父さんは書店で本を手に入れてくる（bundle install）のだが、
ここで司書さんはお父さんがすでに持っている本とそのバージョンが書かれたリスト（Gemfile.lock）を確認します。
その上で「お父さんの行動計画」を見て、持っていない本とその本と依存関係のある本を合わせて渡してくれます。
最後にお父さんが所有している本のリスト（Gemfile.lock）を更新してくれます。

<strong>３ヶ月後、子どもたちもお父さんの行動計画とリストを持って、本を取得しにいきます。

<strong>お父さんと子どもたちは全く同じ計画で「お母さんを楽にしてあげる」という目的を遂行できます。

---
　

#キーワード詳細
#Rubyのライブラリ　「gem」

よくある処理をプログラムの部品としていっぱい詰め込んだものをライブラリという。

例で言うところの本である。
「おいしい料理を作る」
「洗濯を手伝う方法」
これらをライブラリ。つまり「gem」と呼ぶ。

こういった先人の知恵が本という形で無いと、「美味しい料理を作るための方法」を自分で作り上げる必要があるし、「洗濯の方法」も自分で編みだす必要がある。
でもライブラリであれば、それをそのまま持ってくるだけで、これらの技術を使えるようになる。

実際のRailsアプリケーションの場合であれば
「データーベースに接続する」
「テストをする」
「見た目を整える」
「ログイン機能の実装」
「ページネーション機能をつける」

こういった「gem」が用意されている。

#依存関係

gemには依存関係というものがある。
たとえば「美味しい料理を作る」という本は「包丁の使い方2.0」という本を参照することになっている。（依存している）

このようにgemには他のgemを利用しているケースがある。

#RubyGems
```bundle install```でなくてもgemは手に入る。
gemのパッケージマネージャーである「RubyGems」
本を手に入れる方法は書店（```https://rubygems.org```）に行くわけだが、「美味しい料理を作る」を手に入れようとすると```gem install 美味しい料理を作る```のコマンドだけでも「包丁の使い方2.0」を渡してくれる。

それなら、Bundlerの存在意義はなんだ？という話になる。

Bundlerが無いと<strong>急にアプリケーションが動かなくなったり、別の人の環境では動かなくなる</strong>という問題が出現する。

なぜか？
gemはより良くするためにアップデートされていく。
アップデートされると今まで依存関係にあったgemと互換性を保てなくなって上記のような問題が現れる。

もしgemコマンドでお父さんが「美味しい料理の作り方」とその依存関係にある「包丁の使い方2.0」を手に入れたとします。
３ヶ月後、子どもたちが同じくgemコマンドで手に入れた時には「包丁の使い方」はアップデートされていて、
「美味しい料理の作り方」と「包丁の使い方2.5」を入手してしまい、依存関係が崩れる。

#Bundler
Bundlerの登場によりアプリケーションを使うすべての人が、依存するgemも含めて同じgemのバージョンでアプリが動かせるようになりました。

先程の例だと、たとえ「美味しい料理の作り方」の著者が「包丁の使い方2.0以降でもいいよ」としていても、お父さんは「包丁の使い方2.0じゃないといかん！！」と制御できるのが「Bundler」です。
これにより子どもたち（他の開発者）も「包丁の使い方2.0」を用意できます。

このBundlerでバージョンを管理するために、「Gemfile」と「Gemfile.lock」が必要になります。

#Gemfile
このbundlerでインストールされるgemを管理する場所が「Gemfile」

Railsアプリケーションで使う「gem」の一覧を管理するファイル。

```ruby:Gemfile
source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.6'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.7'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# See https://github.com/rails/execjs#readme
# for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster.
# Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5.x'
# Build JSON APIs with ease.
# Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '~> 2.13'
  gem 'selenium-webdriver'
end

group :development do
  # Access an IRB console on exception pages or by using
  # <%= console %> anywhere in the code.
  gem 'web-console'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running
  # in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

# Windows環境ではtzinfo-dataというgemを含める必要があります
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

```
※[Railsチュートリアルより引用](https://railstutorial.jp/chapters/beginning?version=5.1#sec-bundler)


一番上のsourceが先程からちょいちょい出てくる、書店を指定するコードです。

その書店からいろんな本「gem」を取ってくる。
Rails, sqlite2, pumaなどなど。
各gemの機能はおいおい調べるとして、gemの第２引数でバージョンの指定もできる

| 1 | 2 |
|:-:|:-:|
| 引数なし  | 最新verを入れる  |   
| ~>1.1  | 1.1以降〜2.0以前のverに制限  |   
| >=1.0  |  1.0以上のverに制限 |   


※途中で出てくるgroupはgemをインストール場所を指定できる。
開発環境、テスト環境でだけ使うという指定もこのgroupでできる。

#Gemfile.lock
このファイルはbundlerでインストールされた「gem」の一覧が表示されている。
ここには依存関係にあるgemも表示される。

例えば、「Gemfile」には「actioncable」は無いが、これはRailsが依存するgemなので、```bundle install```をするとGemfile.lockには表示されている。（```gem install rails```でもインストールされる）

>Gemfileにgem railsと記載されているとrailsおよびrailsが依存するactioncableがインストールされる
[引用](https://nishinatoshiharu.com/fundamental-gem-knowledge/)


#＋α　bundle execコマンドについて
このコマンドは「Gemfile.lockに書かれているgemを使用する」ものです。

お父さんと子供たちがついに、「お母さんを楽にさせる」を実行します。
ただし、実はこの家には「包丁の使い方1.0」「「包丁の使い方1.67」「包丁の使い方2.0」の本がありました。
使いたいのは「包丁の使い方2.0」で「Gemlock.file」にもそう書いてあります。
```bundle exec```を使わないと、子どもたちが「包丁の使い方1.0」を見て実行し、「お母さんを楽にさせる」が失敗してしまう可能性があります。

そのため、例えば```rails s```のときは```bundle exec rails s```とする必要がある。


#所感・課題
自分の中で理解するためにイメージ化してみたが、冗長になってしまった感が否めない。
当然の基礎知識のような「gem」でも奥深くて、すべては理解できていない。
(bundle installの時にpathオプションは必要なのかどうかなど)

少しづつ前に進みたい。

初回投稿時に、ご指摘をいただいた。完全にBundlerについて誤解していた。
学習と修正の機会を頂き、ありがとうございました。

#引用・参考
https://qiita.com/kamohicokamo/items/ded4cad5be1778547640

https://qiita.com/nishina555/items/1b343d368c5ecec6aecf#:~:text=Gemfile%E3%81%A8%E3%81%AF,%E7%AE%A1%E7%90%86%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B%EF%BC%9F%E3%80%8F&text=%E3%81%A7%E3%81%99%E3%81%AE%E3%81%A7%E3%80%81Rails%E3%82%A2%E3%83%97%E3%83%AA%E3%81%A7,%E3%81%84%E3%81%8F%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

https://nishinatoshiharu.com/fundamental-gem-knowledge/

https://wa3.i-3-i.info/word1473.html

https://pikawaka.com/rails/bundler

http://xxxcaqui.hatenablog.com/entry/2013/02/11/013421

https://qiita.com/kaishuu0123/items/2a91495e7daa8c7783ed