shakacode/cypress-on-rails

Rails 6.1 `stack level too deep` if used alongside DatabaseCleaner

feliperaul opened this issue · 1 comments

Took the weekend to upgrade an app from Rails 5.2 to Rails 6.1.

On cypress/support/index.js, we have a cy.app('clean_database'); call; in clean_database.rb, we have:

DatabaseCleaner.strategy = :truncation, { except: %w(
   some
   table
   names
) }
DatabaseCleaner.clean

The exception we're getting is stack level too deep; tracking this down, the exception occurs when we call results.to_json in lib/cypress_on_rails/middleware.rb#handle_command.

On rails 5.2, results was an array with 1 element, containing:

 [[#<DatabaseCleaner::Base:0x00007f8a67f1fe48
   @db=:default,
   @orm=:active_record,
   @orm_autodetector=#<DatabaseCleaner::ORMAutodetector:0x00007f8a67f1fe20 @autodetected=true>,
   @strategy=
    #<DatabaseCleaner::ActiveRecord::Truncation:0x00007f8a67f1cd38
     @cache_tables=true,
     @connection_class=ActiveRecord::Base,
     @db=:default,
     @only=nil,
     @pre_count=nil,
     @reset_ids=nil,
     @tables_to_exclude=["some", "tables"]>>]]

On rails 6.1, this becomes a huge object, because DatabaseCleaner::Base#strategy contains a enormous DatabaseCleaner::ActiveRecord::Truncation object, because of it's @connection instance variable:

[[#<DatabaseCleaner::Cleaner:0x00007ff23fd228f8
   @db=:default,
   @orm=:active_record,
   @strategy=
    #<DatabaseCleaner::ActiveRecord::Truncation:0x00007ff2472bd4a0
     @cache_tables=true,
     @connection=
      #<ActiveRecord::ConnectionAdapters::PostgreSQLAdapter:0x00007ff2472571c8
       @advisory_locks_enabled=true,
       @config={:adapter=>"postgresql", :database=>"xxxx", :username=>"xxxx", :encoding=>"unicode", :pool=>25, :host=>"localhost", :port=>5432},
       @connection=#<PG::Connection:0x00007ff247257ad8>,
       @connection_parameters={:user=>"xxxx", :dbname=>"xxxxx", :host=>"localhost", :port=>5432},
       @default_timezone=:utc,
       @idle_since=3202867.25819,
       @instrumenter=
        #<ActiveSupport::Notifications::Instrumenter:0x00007ff241833070
         @id="fcd073bdb4c06c97144c",
         @notifier=
          #<ActiveSupport::Notifications::Fanout:0x00007ff23a944128
           @_mutex=#<Thread::Mutex:0x00007ff23fa03f50>,
           @listeners_for=#<Concurrent::Map:0x00007ff23a944060 entries=6 default_proc=nil>,
           @other_subscribers=
            [#<ActiveSupport::Notifications::Fanout::Subscribers::Timed:0x00007ff240a90710
              @can_publish=false,
              @delegate=#<Proc:0x00007ff240a90788 /Users/xxxx/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/dotenv-rails-2.7.6/lib/dotenv/rails.rb:24>,
              @pattern=#<ActiveSupport::Notifications::Fanout::Subscribers::Matcher:0x00007ff240a906e8 @exclusions=#<Set: {}>, @pattern=/^dotenv/>>],
           @string_subscribers=
            {"service_mirror.active_storage"=>
              [#<ActiveSupport::Notifications::Fanout::Subscribers::Evented:0x00007ff23fbd2598

Calling .to_json on this results array results in a stack level too deep.

Is anyone else facing this, and what do the maintainers think, should we handle this on this gem or try to solve it upstream?

I obviously wasn't thinking straight when I opened this.

cypress-on-rails will try to render as json the return of the command called.

It was a simple matter of making our clean_database.rb return true in the last line, instead of returning the call to DatabaseCleaner.clean.

So instead of

DatabaseCleaner.clean

Just

DatabaseCleaner.clean
true