Gemfileにバージョンを指定したり、しなかったり。Gemfileについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111652/ce9b2099-03c1-67fe-874b-826dfda801d7.png)


## はじめに
RailsでGemを使うときに`gem 'kaminari`とか記述しますよね。
ネットの記事を見てると`">= 1.2.3", "< 2.0.0"`とか書かれていてバージョンのこと書いてあるんだろうな〜とは思いつつも、そのままコピペして使ったり、gem名だけ記述したりで使ってますって方結構いるかと思います。

`group`とかあるけど、このアプリはどこに書いたらいいの〜とかわからないなどありますよね？

そこで、そこをクリアにしようとまとめてみます。

## GemfileとGemfile.lock
**Gemfile**とはRailsアプリで利用するライブラリ、**gemが記述されているファイルのこと**です。
Gemfileを参照することで、Railsアプリを動作させるためにはどのgemをインストールすればいいのかがわかります。

**Gemfile.lockはGemfileを元に実際にインストールされたgemに加え、依存関係にあるgemが記述されたファイル**になります。
Gemfile.lockには実際にインストールしたgemの具体的なバージョンも記述されています。

**Gemfileは「アプリで必要なgemリスト」**、**Gemfile.lockで「実際にインストールしたgemリスト」**が記述されています。

## Bundler
Gemは**Bundler**を使ってバージョンを管理します。
BundlerはGemfileの記述にしたがって、Gemの依存関係を示したGemfile.lockを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111652/2489ae1f-1274-be5d-6dfc-8b06c703350b.png)
# Gemfileの中身
Gemfileは通常、こんな感じで書かれています。

```ruby:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.5'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.7'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Active Storage variant
# gem 'image_processing', '~> 1.2'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false

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]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 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

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
```
----

### Gemを取得する場所
一番上にはこのアプリケーションで使う**Rubyのバージョン**や**Rails**のバージョンなどが書かれています。

```ruby:Gemfileの上部分
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.5'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.0'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
# Use Puma as the app server
gem 'puma', '~> 3.11'
```


```ruby
source 'https://rubygems.org'
```
一番上に書かれている**sourceは、gemのホスティングサーバーを指定します。**
gemを管理するBundlerはこのsourceに書かれている場所にコードを取りにいきます。

## Gemのバージョン指定
gemが書かれているところを見ると**`gem 'rails', '~> 6.0.0'`**などと`~>`などと書かれていることがあります。書かれていないGemもあり、その違いとはなんでしょうか？

```ruby:Gemのバージョン指定
gem 'Gem名', 'バージョン', 'オプション'
```

gemは**バージョンを指定することができ**、**バージョン指定しなければ、最新のgem**がインストールされます。

------
### Gemのバージョン指定方法

|指定方法　　　　  | 説明　　　　　　　    　|
|---------------|----------------------|
|'1.0.0' 　　 |バージョンを固定　　    　|
|'>= 1.0.0'   |指定した以降のバージョン　|
|'>= 1.0.0' , '< 2.0.0'    |指定した範囲のバージョン　|
|'~> 1.0.0'   |指定したバージョン以降で、マイナーバージョンが変わらない範囲|
|'~> 1.0'     |指定したバージョン以降で、メジャーバージョンが変わらない範囲|

例えば

```ruby
gem 'rails', '~> 5.1.3'
```
の場合はRailsのバージョン**`5.1.3以上、5.2.0未満`**を指定していることになります。
<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111652/44378684-a056-db7e-6680-18570c6eb30b.png)

## Gemのグループ
Gemfileを見ていると

```ruby
group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
```
と**`group do ~ end`**で囲まれたgemを見ることがあります。
これはインストールする環境の指定を指定しています。
上記の場合は、開発環境とテスト環境でインストールされます。

**`byebug`などの開発中のみに使いたくて、本番環境ではインストールしたくないgemをGemfileで管理することができます。**


**groupの外にあるgemは`default`グループに属します。**

1つのGemを１行でインストールしたい環境を指定する場合はこのように記述します。

```ruby
gem 'qiita_ni_qiita', group: [:development, :test]
```
<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111652/90af4358-469e-c2ac-e11e-f39500a48b30.png)


## 自動的に読み込むファイルを指定する
**Bundlerの特徴として、Gemfileに記述されたGemをまとめて自動で`require`する仕組み**になっています。

```ruby:rubocop
gem 'rubocop', require: false
```

**`require: false**になっています。
コードをいい感じに直してくれる**`rubocop`**。使っている方も多いと思います。
`rubocop`はどんなときにどこで使うでしょうか?
ソースコードが規約に沿っているかを確認するために、ターミナルでコマンドを実行しますよね。

`rubocop`はターミナルで使い、Budlerによってアプリ側で自動で読み込む必要がないため
**`require: false`**と記述されています。


## 終わりに
Gemfileについてまとめてみましたが、すっきりしましたでしょうか？
Railsを使う上で、基本中の基本のGemfile。よくわからず使っている方も多いと思います。
少しでも理解が深まりましたら幸いです。
<br>
<br>
> 参考サイト
- [Qiita Bundler まとめ](https://qiita.com/lmatsul/items/3543ef5d74c8525841dc)
- [Bundler](https://bundler.io/v1.17/man/gemfile.5.html)
- [Site-Builder.wiki　Gemfile の書き方 Ruby/Bundler](https://site-builder.wiki/posts/2565)
- [xxxcaqui.log　Gemfileについて調べてみた](http://xxxcaqui.hatenablog.com/entry/2013/02/11/013421)
- [Yohei Isokawa　【Rails】Gemfileのバージョン指定の書き方](https://blog.yuhiisk.com/archive/2017/04/24/specify-the-version-of-gemfile.html)
- [AUTOVICE　【Rails】忘れがちなGemfileの書き方を総復習](https://www.autovice.jp/articles/118)
- [Enjoy IT Life　【初心者向け】GemfileとGemfile.lockの違い](https://nishinatoshiharu.com/difference-gemfile-gemfilelock/)
- [Qiita　Bundlerでgemを実用的に扱うためのまとめ](https://qiita.com/iguchi1124/items/3c17e1275b9bee4138d7)
- [Ruby STUDIO　Bundlerのグループ](https://ruby.studio-kingdom.com/bundler/guides/groups)
- [現場ログ　Gemfile の グループ化, 明確にしないと予期せぬエラーが起きる (書き留め)](https://mat5ukawa.hateblo.jp/entry/2015/06/14/194049)
- [Qiita　rubocopをbundlerでインストールするときにrequire: falseにする理由](https://qiita.com/S42100254h/items/170e88d888330ca92701)