From 79d1ad22dd0b77f1f03e872d85a3bbeb2b135a8e Mon Sep 17 00:00:00 2001 From: Benoit Tigeot Date: Thu, 23 Nov 2023 19:42:07 +0100 Subject: [PATCH] Fix undefined method config (#440) * CI against Rails 7.1 * Ignore the directory that keeps factory files under the `lib` Some tests put factory files under the `lib`. But since Rails 7.1, Rails loads `lib` directory by default in a new application. https://guides.rubyonrails.org/7_1_release_notes.html#introducing-config-autoload-lib-and-config-autoload-lib-once-for-enhanced-autoloading But factory files don't follow the naming rule of Zeitwerk. So Zeitwerk raises `Zeitwerk::NameError`. To avoid the error, this changed to ignore the directory that puts factory files. * Remove the route that is defined by default Some test code loads the route file twice. This wasn't a problem before Rails 7.0 because we didn't have a route. But, Rails 7.1 has one route by default. So the test application raises the following error during the load. ``` Invalid route name, already in use: 'rails_health_check' (ArgumentError) You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here: https://guides.rubyonrails.org/routing.html#restricting-the-routes-created ``` The routing isn't a matter of this gem, so just ignore that for running the test. * Prevent warning about deprecated cache_format_version * Wrap ActiveRecord configuration into initializer `Rails.application` is not available when the railties are collected, so we move the ActiveRecord configuration into the initializer phase. ``` NoMethodError: undefined method `config' for nil:NilClass (NoMethodError) application.config ^^^^^^^ /project/app/vendor/bundle/ruby/3.2.0/gems/railties-7.0.8/lib/rails.rb:47:in `configuration' /project/app/vendor/bundle/ruby/3.2.0/gems/factory_bot_rails-6.4.0/lib/factory_bot_rails/railtie.rb:25:in `block in ' ``` * Provide non regression feature test when ActiveRecord::Base is loaded It happens if the AR::Base as already been loaded. For example: https://github.com/DatabaseCleaner/database_cleaner-active_record/pull/91 --------- Co-authored-by: Yuji Yaginuma Co-authored-by: Leo Arnold --- .github/workflows/build.yml | 2 +- Appraisals | 11 +++++++++++ features/initializers.feature | 15 +++++++++++++++ features/support/rails_template | 10 ++++++++++ gemfiles/rails7.1.gemfile | 20 ++++++++++++++++++++ lib/factory_bot_rails/railtie.rb | 12 +++++++----- spec/fake_app.rb | 4 ++++ 7 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 features/initializers.feature create mode 100644 gemfiles/rails7.1.gemfile diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1d7e5f3b..cc7c12a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - rails: ["7.0", "6.1"] + rails: ["7.1", "7.0", "6.1"] ruby: ["3.2", "3.1"] include: - rails: "6.1" diff --git a/Appraisals b/Appraisals index f5547698..4400ed69 100644 --- a/Appraisals +++ b/Appraisals @@ -58,3 +58,14 @@ appraise "rails7.0" do gem "spring-watcher-listen", "~> 2.0.0" gem "sqlite3", "~> 1.4" end + +appraise "rails7.1" do + gem "byebug" + gem "error_highlight", ">= 0.4.0" + gem "listen", "~> 3.2" + gem "puma", "~> 6.0" + gem "rails", "~> 7.1.0" + gem "spring", "!= 2.1.1" + gem "spring-watcher-listen", "~> 2.0.0" + gem "sqlite3", "~> 1.4" +end diff --git a/features/initializers.feature b/features/initializers.feature new file mode 100644 index 00000000..823966ce --- /dev/null +++ b/features/initializers.feature @@ -0,0 +1,15 @@ +Feature: properly integrate with Rails and other gems + + Background: + When I create a new rails application + And I add "factory_bot_rails" from this project as a dependency + And I run `bundle install` with a clean environment + + Scenario: handle already loaded ActiveRecord::Base by another gems earlier + When I run the following commands: + """bash + cat config/application.rb + sed -i -e '/require "rails\/test_unit\/railtie"/a\'$'\n''require "active_record/base"' config/application.rb + """ + When I run `bundle exec rake test` with a clean environment + Then the output should contain "0 runs" diff --git a/features/support/rails_template b/features/support/rails_template index 6b085b77..bc53016d 100644 --- a/features/support/rails_template +++ b/features/support/rails_template @@ -3,3 +3,13 @@ if Rails.gem_version < Gem::Version.new('6') end gsub_file "Gemfile", /^ gem 'spring'$/, ' gem "spring", "!= 2.1.1"' + +if Rails.gem_version >= Gem::Version.new('7.1') + append_to_file File.join("config", "application.rb"), <<~RUBY + class TestApp::Application + config.autoload_lib(ignore: %w(some_railtie)) + end + RUBY + + gsub_file "config/routes.rb", /^ get/, ' # get' +end diff --git a/gemfiles/rails7.1.gemfile b/gemfiles/rails7.1.gemfile new file mode 100644 index 00000000..fecb5ba6 --- /dev/null +++ b/gemfiles/rails7.1.gemfile @@ -0,0 +1,20 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "appraisal" +gem "aruba" +gem "cucumber" +gem "error_highlight", ">= 0.4.0" +gem "rake" +gem "rspec-rails" +gem "standard" +gem "byebug" +gem "listen", "~> 3.2" +gem "puma", "~> 6.0" +gem "rails", "~> 7.1.0" +gem "spring", "!= 2.1.1" +gem "spring-watcher-listen", "~> 2.0.0" +gem "sqlite3", "~> 1.4" + +gemspec name: "factory_bot_rails", path: "../" diff --git a/lib/factory_bot_rails/railtie.rb b/lib/factory_bot_rails/railtie.rb index 5512f239..de539cf2 100644 --- a/lib/factory_bot_rails/railtie.rb +++ b/lib/factory_bot_rails/railtie.rb @@ -21,13 +21,15 @@ class Railtie < Rails::Railtie FactoryBot.definition_file_paths = definition_file_paths end - ActiveSupport.on_load :active_record do - config = Rails.configuration.factory_bot + initializer "factory_bot.reject_primary_key_attributes" do + ActiveSupport.on_load :active_record do + config = Rails.configuration.factory_bot - if config.reject_primary_key_attributes - require "factory_bot_rails/factory_validator/active_record_validator" + if config.reject_primary_key_attributes + require "factory_bot_rails/factory_validator/active_record_validator" - config.validator.add_validator FactoryValidator::ActiveRecordValidator.new + config.validator.add_validator FactoryValidator::ActiveRecordValidator.new + end end end diff --git a/spec/fake_app.rb b/spec/fake_app.rb index 37e7b2a3..958850a1 100644 --- a/spec/fake_app.rb +++ b/spec/fake_app.rb @@ -4,6 +4,10 @@ module Dummy class Application < Rails::Application config.eager_load = false config.root = "spec/fixtures" + + if Rails.gem_version >= Gem::Version.new("7.1") + config.active_support.cache_format_version = 7 + end end end