チュートリアルでテストDBまわりで詰まった
「6.2.5 一意性を検証する」で詰まった
簡単にやっていることを説明するとアプリケーションにユーザモデルを定義し、そのユーザモデルの要素であるメールアドレスを一意にするという流れの部分です。
その中で以下の部分で本来redにならないといけないところがgreenになってしまいました。
この時点では、テストDB用のサンプルデータが含まれているfixtures内で一意性の制限が保たれていないため、テストは red になります
チュートリアルの通りでusers.ymlは変更していないのでこの結果はおかしいです。
調査
DBに一意のインデックスが設定されてないのが原因かと思い、確認してみました。
$ sqlite3 db/development.sqlite3
sqlite> select * from sqlite_master where type='index' and name='index_users_on_email';
type = index
name = index_users_on_email
tbl_name = users
rootpage = 8
sql = CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email")
development.sqlite3はちゃんと設定されてます。
しかしながらテストのときはtest.sqlite3が使われるっぽいのでこちらも確認してみました。
$ sqlite3 db/test.sqlite3
sqlite> select * from sqlite_master where type='index' and name='index_users_on_email';
sqlite>
なぜかこちらは設定されてません。
そこでとりあえずテストDBへのマイグレーションをロールバックします。
$ rails db:rollback RAILS_ENV=test
= 20180818045941 AddIndexToUsersEmail: reverting =============================
-- remove_index(:users, {:column=>:email})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
でもインデックスが無く、ロールバックできないとエラーになりました。
これはこの問題が発生する前に私がインデックスを作るときエラーになった原因がわからず以下の作業をしたことが原因だと思います。
- [timestamp]_add_index_to_users_email.rbを空にしてマイグレーション(rails db:migrate)。
- その後ロールバック(rails db:rollback)。
- [timestamp]_add_index_to_users_email.rbにインデックスを記載してマイグレーション(rails db:migrate)。
このことからテストDBもロールバックしたいときは別途で明示的にロールバックしないといけないのかと思っています。
解消方法
ここからは以下の手順で問題を解消しました。
- [timestamp]_add_index_to_users_email.rbを空にしてテストDBをロールバック(rails db:rollback RAILS_ENV=test)。
- [timestamp]_add_index_to_users_email.rbにインデックスを記載してマイグレーション(rails db:migrate RAILS_ENV=test)。
- Usersテーブル内にusers.ymlのデータが入っており2.がエラーとなるのでそのデータを削除(sqlite3でdelete from users;)。
- 2.を再度実施
この手順で想定通りtestがredになり、チュートリアルを先に進められるようになりました。