DatabaseCleaner / database_cleaner

Strategies for cleaning databases in Ruby. Can be used to ensure a clean state for testing.
https://www.rubydoc.info/github/DatabaseCleaner/database_cleaner
MIT License
2.93k stars 484 forks source link

uninitialized constant ActiveRecord::DatabaseConfigurations::ConnectionUrlResolver::URI #686

Open exocode opened 3 years ago

exocode commented 3 years ago

I run my specs on Gitlab CI. When I try to run bundle exec rspec I get:

-----> Running test: bundle exec rspec
An error occurred while loading ./spec/auth/authenticate_user_spec.rb.
Failure/Error: require 'database_cleaner'
NameError:
  uninitialized constant ActiveRecord::DatabaseConfigurations::ConnectionUrlResolver::URI
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations/connection_url_resolver.rb:47:in `uri_parser'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations/connection_url_resolver.rb:25:in `initialize'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations/url_config.rb:48:in `new'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations/url_config.rb:48:in `build_url_hash'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations/url_config.rb:38:in `initialize'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations.rb:262:in `new'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations.rb:262:in `environment_url_config'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations.rb:177:in `build_configs'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/database_configurations.rb:19:in `initialize'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/core.rb:64:in `new'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/core.rb:64:in `configurations='
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/core.rb:66:in `block in <module:Core>'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.3.1/lib/active_support/concern.rb:136:in `class_eval'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.3.1/lib/active_support/concern.rb:136:in `append_features'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/base.rb:282:in `include'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/base.rb:282:in `<class:Base>'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/base.rb:265:in `<module:ActiveRecord>'
# ./vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.1/lib/active_record/base.rb:15:in `<top (required)>'
# ./vendor/bundle/ruby/2.7.0/gems/database_cleaner-active_record-2.0.0/lib/database_cleaner/active_record/truncation.rb:2:in `require'
# ./vendor/bundle/ruby/2.7.0/gems/database_cleaner-active_record-2.0.0/lib/database_cleaner/active_record/truncation.rb:2:in `<top (required)>'
# ./vendor/bundle/ruby/2.7.0/gems/database_cleaner-active_record-2.0.0/lib/database_cleaner/active_record.rb:4:in `require'
# ./vendor/bundle/ruby/2.7.0/gems/database_cleaner-active_record-2.0.0/lib/database_cleaner/active_record.rb:4:in `<top (required)>'
# ./vendor/bundle/ruby/2.7.0/gems/database_cleaner-2.0.1/lib/database_cleaner.rb:1:in `require'
# ./vendor/bundle/ruby/2.7.0/gems/database_cleaner-2.0.1/lib/database_cleaner.rb:1:in `<top (required)>'
# ./spec/rails_helper.rb:3:in `require'
# ./spec/rails_helper.rb:3:in `<top (required)>'
# ./spec/auth/authenticate_user_spec.rb:1:in `require'
# ./spec/auth/authenticate_user_spec.rb:1:in `<top (required)>'
Rails V: 6.1.3.1 - test

ruby '2.7.2'

Gemfile:

group :development, :test do
  gem 'database_cleaner'
end

Gemfile.lock

    database_cleaner (2.0.1)
      database_cleaner-active_record (~> 2.0.0)
    database_cleaner-active_record (2.0.0)
      activerecord (>= 5.a)
      database_cleaner-core (~> 2.0.0)
    database_cleaner-core (2.0.1)

On my internet research I found this:

https://blog.code-fabrik.ch/2021/03/31/sinatra-databaseconfiguration-url.html

olistik commented 2 years ago

I think I found a workaround.

It's not pretty but at least I can now restore tests in my Gitlab CI. 😅

First of all, the issue with URI's name resolution is likely fixable by applying this patch to activerecord (v6.1.4.4 in my case):

diff --git a/lib/active_record/database_configurations/connection_url_resolver.rb b/lib/active_record/database_configurations/connection_url_resolver.rb
index 13fddb9..a136243 100644
--- a/lib/active_record/database_configurations/connection_url_resolver.rb
+++ b/lib/active_record/database_configurations/connection_url_resolver.rb
@@ -1,5 +1,6 @@
 # frozen_string_literal: true

+require "uri"
 require "active_support/core_ext/enumerable"

 module ActiveRecord
@@ -44,7 +45,7 @@ module ActiveRecord
         attr_reader :uri

         def uri_parser
-          @uri_parser ||= URI::Parser.new
+          @uri_parser ||= ::URI::Parser.new
         end

         # Converts the query parameters of the URI into a hash.

As far as I know there's not this kind of fix on 6.x, yet so the question is how to fix it in the meanwhile. I created a testing repository of activerecord v6.1.4.4 here: https://github.com/olistik/activerecord-test/ It contains the abovementioned patch.

Then I put this conditional require in my Gemfile and updated my .gitlab-ci.yml accordingly:

Gemfile:

# Because of an issue faced in Gitlab CI between database_cleaner and activerecord.
# see https://github.com/DatabaseCleaner/database_cleaner/issues/686
if ENV['GITLAB_CI'] == 'true'
  gem 'activerecord', github: 'olistik/activerecord-test'
end

.gitlab-ci.yml:

  - GITLAB_CI=true bundle install --no-binstubs -j $(nproc) --path vendor # Install dependencies

Hope to be helpful for someone in a similar situation. <3 Feel free to propose better solutions. 🎩

olistik commented 2 years ago

I upgraded Rails to 6.1.6 and the problem somehow disappeared from my pipeline. I did a quick scan of Rails' changelog but couldn't find a direct fix so 🤷🏻‍♂️ 😅