はじめに
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
- ブラウザからアクセスすると、エラーが発生する
調査してみる
上の方からスタックトレースをみていく
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ドキュメントを参照)
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
動いた
もう少し調べてみる(おまけ)
どうして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できる。こっちの方が賢い。
所感
あんまり大した記事じゃないのに長くなってしまった…
でもバグに当たった時にソースみながら調査するって結構大事だな、と思った。(あまりやってないけど)
もっと深い所まで理解できる様になっていきたいな。