Skip to content

Commit

Permalink
Fix undefined method config (#440)
Browse files Browse the repository at this point in the history
* 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 <class:Railtie>'
```

* Provide non regression feature test when ActiveRecord::Base is loaded

It happens if the AR::Base as already been loaded.

For example:
DatabaseCleaner/database_cleaner-active_record#91

---------

Co-authored-by: Yuji Yaginuma <yuuji.yaginuma@gmail.com>
Co-authored-by: Leo Arnold <github@leoarnold.de>
  • Loading branch information
3 people committed Nov 23, 2023
1 parent 8b2a78e commit 79d1ad2
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Expand Up @@ -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"
Expand Down
11 changes: 11 additions & 0 deletions Appraisals
Expand Up @@ -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
15 changes: 15 additions & 0 deletions 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"
10 changes: 10 additions & 0 deletions features/support/rails_template
Expand Up @@ -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
20 changes: 20 additions & 0 deletions 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: "../"
12 changes: 7 additions & 5 deletions lib/factory_bot_rails/railtie.rb
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions spec/fake_app.rb
Expand Up @@ -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

Expand Down

0 comments on commit 79d1ad2

Please sign in to comment.