Rails APIモードでspringを使ってRSpecを起動しようとしたんですが、config.cache_classes
の設定の仕方がわからずハマったため、備忘録としてまとめます。
バージョン
- Ruby 3.2.2
- Rails 7.1.2
記事の信頼性
- ぼくは独学で未経験から従業員300名以上の自社開発企業へ転職しました。
- 実務ではVue.jsとRailsを毎日書いています。
- 初心者や駆け出しエンジニアがつまづくポイントも身をもってよく理解しています。
問題とやったこと
RailsのAPIモードを使ってTODOアプリを作ろうとしていました。
実践的にやりたいと思い、springを使ってRSpecを起動させようと考えました。
そのためにやったことは以下のとおりです。
①Gemfile に gem を追加し bundle install を実行
次のように、Gemfile にrspec-rails
とspring-commands-rspec
を追加し、bundle install
を実行しました。
group :development, :test do
gem 'rspec-rails', '~> 6.1.0'
end
group :development do
gem 'spring-commands-rspec'
end
※ぼくはDocker環境を構築しているため、docker compose build --no-cache
も実行しています。
②RSpecを動かすために必要なファイルの作成と実行確認
次に、springをつかわずにRSpecが実行できることを確認しました。
todo-app % docker compose run --rm rails bundle exec rails g rspec:install
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
todo-app % docker compose run --rm rails bundle exec rspec
[+] Running 1/0
✔ Container todo-app-db-1 Running 0.0s
No examples found.
Finished in 0.00027 seconds (files took 0.06623 seconds to load)
0 examples, 0 failures
todo-app %
なのでRSpecの設定は問題なさそう。
③spring用のファイルを作成
続いてbundle exec spring binstub rspec
コマンドで、spring用のファイルbin/rspec
を作成します。
todo-app % docker compose run --rm rails bundle exec spring binstub rspec
* bin/spring: generated with Spring
* bin/rspec: generated with Spring
todo-app % ls bin/
bundle docker-entrypoint rails rake rspec setup spring
todo-app %
無事に作成できました。
④springを使ってRSpecを実行したところ、、、
これで設定完了と思い、springを使ってRSpecの実行を試みたところ、次のエラーが出ました、、。
todo-app % docker compose run --rm rails bin/rspec
[+] Running 1/0
✔ Container todo-app-db-1 Running 0.0s
/usr/local/bundle/gems/spring-4.1.3/lib/spring/application.rb:100:in `block in preload': Spring reloads, and therefore needs the application to have reloading enabled.
Please, set config.cache_classes to false in config/environments/test.rb.
(RuntimeError)
...
todo-app %
エラーメッセージを元に調べたところ、config/environments/test.rb
にconfig.cache_classes = false
と設定すれば良さそうでした。
しかし、config/environment/test.rb
にはconfig.cache_classes
という設定が存在しておらず、どうしていいかわかりませんでした、、。
現状のconfig/environment/test.rb
は次のとおりです。
require "active_support/core_ext/integer/time"
# 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!
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# While tests run files are not watched, reloading is not necessary.
config.enable_reloading = false
# Eager loading loads your entire application. When running a single test locally,
# this is usually not necessary, and can slow down your test suite. However, it's
# recommended that you enable it in continuous integration systems to ensure eager
# loading is working properly before deploying your code.
config.eager_load = ENV["CI"].present?
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.cache_store = :null_store
# Render exception templates for rescuable exceptions and raise for other exceptions.
config.action_dispatch.show_exceptions = :rescuable
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test
config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raise exceptions for disallowed deprecations.
config.active_support.disallowed_deprecation = :raise
# Tell Active Support which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
# Raise error when a before_action's only/except options reference missing actions
config.action_controller.raise_on_missing_callback_actions = true
end
解決方法
結論として、Rails7.1以降ではconfig.cache_classes
という記述は使われておらず、代わりにconfig.enable_reloading
が導入されていました。
config.enable_reloading
はデフォルトでtrue
ですが、これをfalse
に変更すればRails7.1以前のconfig.cache_classes = false
と同じことが実現できます。
require "active_support/core_ext/integer/time"
# 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!
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# While tests run files are not watched, reloading is not necessary.
config.enable_reloading = true ← ここを false から true に変更!
# Eager loading loads your entire application. When running a single test locally,
# this is usually not necessary, and can slow down your test suite. However, it's
# recommended that you enable it in continuous integration systems to ensure eager
# loading is working properly before deploying your code.
config.eager_load = ENV["CI"].present?
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.cache_store = :null_store
# Render exception templates for rescuable exceptions and raise for other exceptions.
config.action_dispatch.show_exceptions = :rescuable
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test
config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raise exceptions for disallowed deprecations.
config.active_support.disallowed_deprecation = :raise
# Tell Active Support which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
# Raise error when a before_action's only/except options reference missing actions
config.action_controller.raise_on_missing_callback_actions = true
end
これで再度コマンドを実行してみると、、、
todo-app % docker compose run --rm rails bin/rspec
[+] Running 1/0
✔ Container todo-app-db-1 Running 0.0s
Running via Spring preloader in process 17
No examples found.
Finished in 0.00036 seconds (files took 0.15969 seconds to load)
0 examples, 0 failures
todo-app %
無事にRSpecが実行できました!
※Rails7.1以前の場合は、config.cache_classes = true
という記述がデフォルトで存在しているはずなので、それをfalse
にすれば問題ありません。
おわりに
公式ドキュメントを精読したことで原因を特定できました。一次情報は大事ですね。
コメント