DatabaseCleaner / database_cleaner-active_record

Strategies for cleaning databases using ActiveRecord. Can be used to ensure a clean state for testing.
MIT License
64 stars 63 forks source link

Rails 6 with database_cleaner-active_record ~>1.8 wipe all tables even with except #44

Closed bf39l closed 3 years ago

bf39l commented 4 years ago

database: postgresql 11 Rails 6 rspc-rails ~>4.0 database_cleaner-active_record ~>1.8 spec_helper.rb

  require 'database_cleaner-active_record'
  DatabaseCleaner[:active_record, connection: :test]

  tables_to_be_excluded = %w[public.spatial_ref_sys public.foo]

  config.before(:suite) do
    load "#{Rails.root}/db/seeds.rb"
    DatabaseCleaner.strategy = :truncation, { except: tables_to_be_excluded }
    DatabaseCleaner.clean_with(:truncation, { except: tables_to_be_excluded })
    puts 'Cleaned up database and feed seeds'
    # this step will wipe all data in all tables
  end
  config.before(:each) do
    DatabaseCleaner.start
  end
  config.after(:each) do
    DatabaseCleaner.clean
  end
bf39l commented 4 years ago

I updated gem to database_cleaner, = 1.7.0 with following rspec config

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation, { except: tables_to_be_excluded }
    DatabaseCleaner.clean_with(:truncation, { except: tables_to_be_excluded })
    load "#{Rails.root}/db/seeds.rb"
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :truncation, { except: tables_to_be_excluded }
    DatabaseCleaner.clean_with(:truncation, { except: tables_to_be_excluded })
  end

And confirmed database_cleaner just clean up required tables. UPDATE: also tested with gem database_cleaner 1.8.5, it cleaned up required tables

bsuchodolski commented 3 years ago

I've just spent an afternoon to debug similar problem and I've found out that if you are using postgres then tables are truncated with CASCADE option which truncates not only tables that are not in except option but if any of these tables reference table that is truncated, it will be silently truncated as well despite being in except.

bf39l commented 3 years ago

Right, that kinda make sense, just wondering if I have two tables like below Table "students": id (pk), name Table "classrooms": id (pk), student_id (fk =>id from students) When I clean tuples in classrooms, will it clean up students?

bsuchodolski commented 3 years ago

It's rather other way around. If you exclude classrooms from being truncated and try to truncate all other tables, so in this case only students table, students table cannot be removed separately from classrooms as classrooms references student_id. So with CASCADE option classrooms will be silently truncated as well despite excluding it from being truncated.

Postgres TRUNCATE command can be run with RESTRICT option which does the opposite to CASCADE, if reference like that is found truncation will fail with pretty self-explanatory error message. I've created another issue to maybe add an option to use RESTRICT instead of CASCADE https://github.com/DatabaseCleaner/database_cleaner-active_record/issues/57

bf39l commented 3 years ago

Understood now. I will close this issue now and head back to that project to give a try. Thank you @bsuchodolski .