RailsでSQLite3使う時はgemのバージョンを指定しないといけない

# はじめに
Railsを勉強すべくチュートリアルやってみたが、
SQLite3関連でエラーが起きたので調べてみた

# 環境
- OS: MacOS Mojave 10.14.3
- ruby: 2.3.7
- rails: 5.2.2
- SQLite3: 3.24.0

# 再現方法

- テスト用のアプリを作成し、サーバを起動する  

```
% rails new sqlite3_test  
% cd sqlite3_test && rails server
```  

- ブラウザからアクセスすると、エラーが発生する
<img width="1436" alt="rails_error.png" src="https://qiita-image-store.s3.amazonaws.com/0/167729/9689f13a-b551-0f87-0cbe-bed0a2abdcf0.png">

# 調査してみる

上の方からスタックトレースをみていく

```
Puma caught this error: Error loading the 'sqlite3' Active Record adapter. Missing a gem it depends on? can't activate sqlite3 (~> 1.3.6), already activated sqlite3-1.4.0. Make sure all dependencies are added to Gemfile. (LoadError)
/Library/Ruby/Gems/2.3.0/gems/bundler-2.0.1/lib/bundler/rubygems_integration.rb:408:in `block (2 levels) in replace_gem'
/Library/Ruby/Gems/2.3.0/gems/activerecord-5.2.2/lib/active_record/connection_adapters/sqlite3_adapter.rb:12:in `<main>'
/Library/Ruby/Gems/2.3.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/Library/Ruby/Gems/2.3.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
```

最初のメッセージを読むと、sqlite3のgemは1.3.xしか使えないのに、1.4.0を使おうとしているようだ。
(gemのバージョン指定方法は[railsドキュメント](http://railsdoc.com/references/gemfile)を参照)

`Missing a gem it depends on? can't activate sqlite3 (~> 1.3.6), already activated sqlite3-1.4.0. Make sure all dependencies are added to Gemfile. (LoadError)`

どうやらsqlite3の1.4.0をインストールしてそれを使おうとしているらしい。
gemのバージョンを調べてみる。

```
% gem list | grep sqlite3
sqlite3 (1.4.0)
```

Gemfileも確認してみる。

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

ruby '2.3.7'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.2'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
```

sqlite3のバージョンを指定していないので、最新版(今は1.4.0)をインストールしているらしい。
ということは、ここを書き換えて1.3.xだけインストールするようにすれば解決するはず。

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

ruby '2.3.7'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.2'
# Use sqlite3 as the database for Active Record
# バージョン番号を'~> 1.3.6'に指定
+ gem 'sqlite3', '~> 1.3.6'
```

`bundle install`して、gemを更新し、サーバを起動する。

```
% bundle install --clean
% rails server
```

アクセスしてみる
<img width="1440" alt="スクリーンショット 2019-02-16 23.26.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/167729/a92f94db-29e6-ad7b-fed8-270f99026fea.png">

動いた

# もう少し調べてみる(おまけ)

どうして1.4.0だと弾いてしまうのだろう？
気になったので、ソースコードを追ってもう少し調べてみる

さっきのスタックトレースを上からみていく

- `/Library/Ruby/Gems/2.3.0/gems/bundler-2.0.1/lib/bundler/rubygems_integration.rb:in block (2 levels) in replace_gem`
bundler側なので、多分関係ない

- `/Library/Ruby/Gems/2.3.0/gems/activerecord-5.2.2/lib/active_record/connection_adapters/sqlite3_adapter.rb:12:in <main>'`
ちょっと怪しいのでみてみる

```
% less /Library/Ruby/Gems/2.3.0/gems/activerecord-5.2.2/lib/active_record/connection_adapters/sqlite3_adapter.rb
# frozen_string_literal: true

require "active_record/connection_adapters/abstract_adapter"
require "active_record/connection_adapters/statement_pool"
require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
require "active_record/connection_adapters/sqlite3/quoting"
require "active_record/connection_adapters/sqlite3/schema_creation"
require "active_record/connection_adapters/sqlite3/schema_definitions"
require "active_record/connection_adapters/sqlite3/schema_dumper"
require "active_record/connection_adapters/sqlite3/schema_statements"

gem "sqlite3", "~> 1.3.6"
require "sqlite3"

```

`gem "sqlite3", "~> 1.3.6"` が明らかにおかしい。
これだと1.3.xしか使えないので、1.4.0は当然使えない。

ここを以下の様に書き換えてみると、sqlite3が1.4.0でも動く(動作確認結果は割愛)

```
% vim /Library/Ruby/Gems/2.3.0/gems/activerecord-5.2.2/lib/active_record/connection_adapters/sqlite3_adapter.rb

# frozen_string_literal: true

require "active_record/connection_adapters/abstract_adapter"
require "active_record/connection_adapters/statement_pool"
require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
require "active_record/connection_adapters/sqlite3/quoting"
require "active_record/connection_adapters/sqlite3/schema_creation"
require "active_record/connection_adapters/sqlite3/schema_definitions"
require "active_record/connection_adapters/sqlite3/schema_dumper"
require "active_record/connection_adapters/sqlite3/schema_statements"

# 下記の書き方をすると、1.xで動作する様になる。
# すごく雑なバージョン指定だけど、動作検証のためこうしている。
gem "sqlite3", "~> 1.3"
require "sqlite3"
```

# 結論

実はこちらの記事で大体のところが書いてあった。
https://qiita.com/Kta-M/items/254a1ba141827a989cb7

sqlite3の1.4.0が2/4にリリースされたが、railsの方がまだ対応できておらずこうなっているらしい。
既に修正のためのプルリク↓が承認されているので、もうじき直るとのこと。(じゃあこの記事いらないじゃん…)
https://github.com/rails/rails/commit/6d5f2511e6d9b95a8ac8399c234aa6cd074af51d

PRだとこう直してる

```
require "active_record/connection_adapters/sqlite3/schema_dumper"
require "active_record/connection_adapters/sqlite3/schema_statements"

- gem "sqlite3", "~> 1.3.6"
+ gem "sqlite3", "~> 1.3", ">= 1.3.6"
```

これなら、1.xかつ1.3.6以上のバージョンに限定してrequireできる。こっちの方が賢い。

# 所感

あんまり大した記事じゃないのに長くなってしまった…
でもバグに当たった時にソースみながら調査するって結構大事だな、と思った。(あまりやってないけど)

もっと深い所まで理解できる様になっていきたいな。

# 参考

- https://github.com/rails
- https://qiita.com/Kta-M/items/254a1ba141827a989cb7
- http://railsdoc.com/references/gemfile