palkan / isolator

Detect non-atomic interactions within DB transactions
MIT License
876 stars 26 forks source link

Errors when combined with `ActiveStorage::FixtureSet.blob` #67

Open evdevdev opened 1 year ago

evdevdev commented 1 year ago

What did you do?

We have a Rails 7 app which makes use of fixtures. Specifically, we're using FixtureSet to saturate ActiveStorage files.

When I add isolator to the app, my fixtures start throwing errors.

What did you expect to happen?

Fixtures to work as normally.

What actually happened?

Fixtures fail with the following backtrace:

 /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/testing/file_fixtures.rb:27:in `join'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/testing/file_fixtures.rb:27:in `file_fixture'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activestorage-7.0.7.2/lib/active_storage/fixture_set.rb:65:in `prepare'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activestorage-7.0.7.2/lib/active_storage/fixture_set.rb:61:in `blob'
    /Users/evan/Projects/get-weatherized/quote-app/test/fixtures/active_storage/blobs.yml:2:in `get_binding'
    /Users/evan/.rvm/rubies/ruby-3.2.2/lib/ruby/3.2.0/erb.rb:429:in `eval'
    /Users/evan/.rvm/rubies/ruby-3.2.2/lib/ruby/3.2.0/erb.rb:429:in `result'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/configuration_file.rb:48:in `render'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/configuration_file.rb:22:in `parse'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/configuration_file.rb:18:in `parse'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:53:in `raw_rows'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:42:in `config_row'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:28:in `model_class'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:725:in `block (2 levels) in read_fixture_files'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:16:in `open'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:724:in `block in read_fixture_files'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:723:in `each'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:723:in `each_with_object'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:723:in `read_fixture_files'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:657:in `initialize'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:598:in `new'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:598:in `block in read_and_insert'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:596:in `map'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:596:in `read_and_insert'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:567:in `create_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/test_fixtures.rb:275:in `load_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/test_fixtures.rb:125:in `setup_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/isolator-0.10.0/lib/isolator/railtie.rb:38:in `setup_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/test_fixtures.rb:10:in `before_setup'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/testing/setup_and_teardown.rb:40:in `before_setup'

Additional context

Environment

Ruby Version: 3.2.2

Framework Version (Rails, whatever): Rails 7.0.7

Isolator Version: 0.10.0

palkan commented 1 year ago

Thanks for the report and the backtrace!

Can you also share an exception itself? The backtrace doesn't have any traces of Isolator.

evdevdev commented 1 year ago

More complete backtrace below. Isolator appears 3rd line from the bottom.

TypeError: no implicit conversion of nil into String
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/testing/file_fixtures.rb:27:in `join'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/testing/file_fixtures.rb:27:in `file_fixture'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activestorage-7.0.7.2/lib/active_storage/fixture_set.rb:65:in `prepare'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activestorage-7.0.7.2/lib/active_storage/fixture_set.rb:61:in `blob'
    /Users/evan/Projects/get-weatherized/quote-app/test/fixtures/active_storage/blobs.yml:2:in `get_binding'
    /Users/evan/.rvm/rubies/ruby-3.2.2/lib/ruby/3.2.0/erb.rb:429:in `eval'
    /Users/evan/.rvm/rubies/ruby-3.2.2/lib/ruby/3.2.0/erb.rb:429:in `result'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/configuration_file.rb:48:in `render'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/configuration_file.rb:22:in `parse'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/configuration_file.rb:18:in `parse'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:53:in `raw_rows'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:42:in `config_row'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:28:in `model_class'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:725:in `block (2 levels) in read_fixture_files'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixture_set/file.rb:16:in `open'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:724:in `block in read_fixture_files'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:723:in `each'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:723:in `each_with_object'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:723:in `read_fixture_files'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:657:in `initialize'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:598:in `new'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:598:in `block in read_and_insert'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:596:in `map'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:596:in `read_and_insert'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/fixtures.rb:567:in `create_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/test_fixtures.rb:275:in `load_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/test_fixtures.rb:125:in `setup_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/isolator-0.10.0/lib/isolator/railtie.rb:38:in `setup_fixtures'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activerecord-7.0.7.2/lib/active_record/test_fixtures.rb:10:in `before_setup'
    /Users/evan/.rvm/gems/ruby-3.2.2@quote_app_dev/gems/activesupport-7.0.7.2/lib/active_support/testing/setup_and_teardown.rb:40:in `before_setup'
palkan commented 1 year ago

Thanks!

This line is just calling super: https://github.com/palkan/isolator/blob/b3e918fb69bd887beece7f2a4df5cb1275a6724c/lib/isolator/railtie.rb#L38

The exception comes from the file_fixture helper: https://github.com/rails/rails/blob/274bc97d63f9e29129851a99c00fd2cefe97cfcf/activesupport/lib/active_support/testing/file_fixtures.rb#L27

It seems that the file_fixture_path is not configured.

evdevdev commented 1 year ago

Interesting. If I put a debugger statement in one of my tests, I get a result:

(ruby) ActiveStorage::FixtureSet.file_fixture_path
#<Pathname:/Users/evan/Projects/example-project/test/fixtures/files>

I am always a bit uncertain about rails internals, but it looks to me like the default is getting set here.

Perhaps isolator is making this call before ActiveStorage is loaded?

palkan commented 1 year ago

Perhaps isolator is making this call before ActiveStorage is loaded?

Isolator doesn't call #setup_fixtures, it just extends it, so 🤷‍♂️As I understand, removing isolator fixes the problem, right?

I checked in of my projects using fixtures (following the ActiveStorage setup from the docs) and couldn't reproduce the problem.