0
0

RspecにおけるActiveRecord::StatementInvalid: Mysql2::Error: This connection is in use by: #<Fiber:..>への対処

Last updated at Posted at 2024-08-15

はじめに

実装をしている最中に以下のようなエラーが発生した。

 Failure/Error: _query(sql, @query_options.merge(options))

     ActiveRecord::StatementInvalid:
       Mysql2::Error: This connection is in use by: #<Fiber:0x0000000111111111 (resumed)>

このエラーの解決に少々手間がかかったので、まとめる。

実行バージョン

ruby 3.2.3
Rails 7.1.3
rspec-rails 6.1.3

解決策

ActiveRecordモデルのhas_one_attachedマクロに対して、dependent: :destroyを追加する

変更前

class Hoge < ApplicationRecord
  has_one_attached :csv
end

変更後

class Hoge < ApplicationRecord
  has_one_attached :csv, dependent: :destroy
end

エラーの原因について

公式ドキュメントには以下のように書いてあった。

If the :dependent option isn’t set, the attachment will be purged (i.e. destroyed) whenever the record is destroyed.

dependent オプションを特に指定しない場合デフォルトでdependent: :destroyを指定しなくても良いと書かれていたので、この対応はスルーしていたが、結果的にはここの設定を明示的に行なっていないことが原因だった。

直接的な原因が何なのかはわかっていないが、dependent: :destroyを明示的に書くことでエラーは解決できた。
想定される直接的な原因としては

  • ドキュメントと実際の実装に乖離がある
  • テスト環境でのみうまく作用しない
  • 親リソース起点でdestroyを実行するとうまくいかない

などが考えられる。

エラー解決に躓いた原因

エラーメッセージから読み取れる情報としては、すでにdbコネクションがFiberによって使われているからdbアクセスうまくできないといった趣旨だった。

つまり、エラーが発生しているテストケース以前に何かしらのエラーの原因となるテストケースが存在しているというふわっとしたことしか把握できなかった。

エラー解決に役立った方法

今回はエラーが起きているテストケースのファイル以前にどのspecファイルが実行されているのかを把握する必要があった。そのため、今回のケースでは以下のやり方で、デバッグするのが効率的だった。

方法は、rspec_helper.rb の末尾に次のコードを埋め込むだけ。

rspec_helper.rb
RSpec.configure do |config|
  config.before(:all) do
    puts "\nRunning: #{self.class.metadata[:file_path]}"
  end
end

このコードを埋め込むことで、どのファイル順でrspecが実行されているのかがすぐわかる。

他のやり方としては、rspecが用意しているoptionsを使うという選択肢もある。
rspec -format documentationを使うことで、どのファイルのテストケースが実行されているかをログから容易に把握できる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0