Ruby
Rails
RSpec

RailsでDBのレコードが”時々”なくなる!?

More than 3 years have passed since last update.

私が弊社に入る前からDBのレコードが全て消えるという現象が発生していて

今回私が原因っぽいところを発見して解決するまでの軌跡を。。。

※ 追記(ご注意)

この時の環境は複数ユーザー間でデータを共有したかったと言う

特殊な環境で発生した現象です。

基本はローカルに開発用DBとテスト用DBを建ててくださいね。


環境


  • Rails 4.1.8

  • Rspec 3.0.4(rspec-rails)


問題

単体テストを流すDBにデータ(レコード)が必要だったからです。

本当だったらFactoryGirl等で初期データを登録する等もあるんですが。。。


結論(先出し)


rails_helper.rb

# Checks for pending migrations before tests are run.

# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

この一行はRailsのバージョン4.1以降から対応しているもので

実行環境のDBと現在のマイグレーションの差分を検知し、

自動的にマイグレーションを掛けてくれるというものです。

この差分を検知し、自動的にマイグレーションをかける際に

DBを一度DROPしてからマイグレーションを流すため

DBの全レコードが無くなっていました。


解決


/config/environments/target.rb

  config.active_record.maintain_test_schema = false


を付加することで、差分を検知したとしても

そのままフローが進むように設定することが出来ます。

つまりデータ(レコード)は残る!!

※ 設定内容に関しては下のリンクから確認できます。


発見まで

上記のように弊社に入社してから度々DBの全レコードが無くなる現象が発生していた。


私は最近バックエンドの修正でRailsプロジェクトの開発を行っていて、

なぜか私が単体テストを流す度にDBの全データが無くなっていた。

この辺りで、当Railsプロジェクト。

さらに言えば、マイグレーション周辺がおかしいんだろうと言うアタリをつけて

持っていたタスクそっちのけで調査していた。

Rails初心者なのでRailsが悪いのか、Rspecが悪いのか、ActiveRecordが悪いのか

調査するのには時間が掛かりました(汗

まずは実行環境に目を付けました。


原因1(?) 実行環境(test)自体

Railsには3つの実行環境が標準で存在しています。


  • production -本番環境

  • test -テスト機

  • development -開発機

私は、Railsは規約を重んじていたよね?ということで

testの実行環境は問答無用でテスト開始前に全レコードを削除しているのでは?と言う事で


実行環境(test)を別名にして実行してみた。(”時々”はどこに。。。)

案の定間違っていたので、実行環境毎の設定ファイルを眺めてみることに。



※ここで罠が...


config/environment/test.rb

# The test environment is used exclusively to run your application's

# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true

私の英語力に問題があったと思いますが、


config.cache_classes = trueであればDBがリセットされると勘違いしてしまいました。


実際は上記の結論なので。



原因2(?) 実行環境の設定

該当する実行環境以外では全レコードが無くなる現象は起きなかったため


他の実行環境をコピーした。

だが、ここでも意味はなかった。

次に、そもそもとしてどのようなSQLが流れているのかちゃんと確認しようということでログ・ファイルを確認した。

ログはroot直下のlogディレクトリに実行環境毎にあった。


中を見ると、

DROP DATABASE IF EXISTS `database_name`

DROPが。。。流れてる!!?

DROPが流れているということでRspec関連ファイルの


  • spec_helper.rb

  • rails_helper.rb

を見てみることに。


ここから順繰り中身を見ていって結論に記載している

# Checks for pending migrations before tests are run.

# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

が問題だと判明しました。


使用したコマンド達

1$ RAILS_ENV=test bundle exec rake db:migrate

2$ bundle exec rspec path_to_file.rb


  • 1$

    実行環境を指定(test)し、マイグレーションを行う。


  • 2$

    Rspecで単体テストを流す。



最後

そもそもテスト流す前にマイグレーション掛けようぜ!?


参考リンク