amatsuda / database_rewinder

minimalist's tiny and ultra-fast database cleaner
MIT License
807 stars 91 forks source link

[BUG REPORT] NoMethodError: undefined method `query' for nil:NilClass #43

Closed sachin21 closed 7 years ago

sachin21 commented 7 years ago

An error occurred when factory_girl's create method is executed. It looks like factory_girl's problem but when I am using database_cleaner, RSpec execution all is well so I think database_rewinder's problem.

Environment information

What

A configuration file for database_rewinder

I tried these configuration codes

Case 1: Replaced DatabaseCleaner with DatabaseRewinder

# spec/support/database_rewinder.rb 
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseRewinder.strategy = :transaction
    DatabaseRewinder.clean_with :truncation
  end

  config.before do |ex|
    DatabaseRewinder.strategy = if ex.metadata[:js]
                                 :truncation
                               else
                                 :transaction
                               end
  end

  config.before do
    DatabaseRewinder.start
  end

  config.append_after do
    Capybara.reset_session!
    DatabaseRewinder.clean
  end
end

Case 2: Syntax accourding to database_cleaner

# spec/support/database_rewinder.rb  
RSpec.configure do |config|
  config.before :suite do
    DatabaseRewinder.clean_with :truncation
    DatabaseRewinder.strategy = :transaction
  end

  config.before do |example|
    DatabaseRewinder.strategy = if example.metadata[:js]
                                 :truncation
                               else
                                 :transaction
                               end
  end

  config.around do |example|
    DatabaseRewinder.cleaning do
      example.run
    end
  end
end

However, those will occur the following error.

Error message

/home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:305:in `block in execute': NoMethodError: undefined method `query' for nil:NilClass (ActiveRecord::StatementInvalid)
Did you mean?  to_query: SHOW FULL FIELDS FROM `something_table`
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:472:in `block in log'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `log'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:305:in `execute'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/database_rewinder-0.6.5/lib/database_rewinder/active_record_monkey.rb:5:in `execute'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/mysql2_adapter.rb:231:in `execute'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:312:in `execute_and_free'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:459:in `columns'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/attributes.rb:93:in `columns'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/attributes.rb:98:in `columns_hash'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:205:in `subclass_from_attributes?'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:54:in `new'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:33:in `create'
        from /home/sachin21dev/Projects/github.com/username/product_name/db/seeds/fixtures/something_table.rb:1:in `<top (required)>'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `load'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `block in load'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:240:in `load_dependency'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `load'
        from /home/sachin21dev/Projects/github.com/username/product_name/spec/support/database_rewinder.rb:6:in `block (2 levels) in <top (required)>'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:425:in `instance_exec'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:425:in `instance_exec'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/hooks.rb:357:in `run'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1724:in `block in run_hooks_with'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1724:in `each'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1724:in `run_hooks_with'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1679:in `with_suite_hooks'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:118:in `block in run_specs'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/reporter.rb:77:in `report'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:117:in `run_specs'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:93:in `run'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:78:in `run'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:45:in `invoke'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.4.4/exe/rspec:4:in `<top (required)>'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `load'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `block in load'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:240:in `load_dependency'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `load'
        from /home/sachin21dev/Projects/github.com/username/product_name/vendor/bundle/ruby/2.3.0/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call'
        from /home/sachin21dev/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /home/sachin21dev/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
sachin21 commented 7 years ago

@amatsuda @deeeki How about this?

deeeki commented 7 years ago

You should try the following.

  1. Regenerate rails_helper.rb using rails g rspec:install
  2. Configure DatabaseRewinder in rails_helper.rb, not in spec/support

If it doesn't work, please create and show your own repository to reproduce the same error.

sachin21 commented 7 years ago

Thank you for suggesting to how to reproduce. I'll try and report that at tonight.

sachin21 commented 7 years ago

@deeeki @amatsuda I'm really sorry. I created supporting files for factory_girl, shoulda_matchers and database_rewinder then It works for me. I will be closing this issue. I think this problem is not a bug of database_rewinder. I sincerely apologize again. But I will report how to solve this problem later.

sachin21 commented 7 years ago

I found the cause. My project has ActiveRecord::Base's monkey patch. If removed this file, it works.

class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil

  def self.connection
    @@shared_connection || retrieve_connection
  end

  def self.clear_all_connections!
    @@shared_connection = nil
    super
  end
end

# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

# 競合回避のため、Mysql2::Client#queryをMutex#synchronizeでラップする
# see: https://gist.github.com/josevalim/470808#gistcomment-1415458
module MutexLockedQuerying
  @@semaphore = Mutex.new

  def query(*)
    @@semaphore.synchronize { super }
  end
end

Mysql2::Client.prepend(MutexLockedQuerying)