Dual booting when there is a breaking database change

Viewed 45

I am upgrading an app from 6.0 to 6.1, using the next_rails dual boot gem. As part of the upgrade I needed to execute rails active_storage:update which adds a service_name to the ActiveStorage::Blob table. When I run my tests with next rspec spec this works fine, but rspec spec fails with tests that use active_storage with messages like

ActiveRecord::NotNullViolation:
        PG::NotNullViolation: ERROR:  null value in column "service_name" violates not-null constraint

Is there a way of adding some conditional code (if Rails::VERSION::MINOR) that detects the version is 6.0 and somehow removes the null constraint for the service_name column.

1 Answers

There are two approaches.

Migrate down to the version before the update:

if Rails.version == "6.0.0"
  ActiveRecord::Base.connection.migration_context.migrate(20220816031332)
else
  ActiveRecord::Base.connection.migration_context.migrate
end

# or maybe invoke the db:migrate tasks instead

You might need to turn off pending migration check: config.active_record.migration_error = false

This approach is general and should work with any migration(s).


The second approach is to call migration helpers manually. This is specific to the problem posed in this question and just changes the columns without updating migration version in the database:

if Rails.version == "6.0.0"
  ActiveRecord::Migration.change_column_null(:active_storage_blobs, :service_name, true)
else
  ActiveRecord::Migration.change_column_null(:active_storage_blobs, :service_name, false)
end

The code can be placed in config/environment.rb after Rails.application.initialize!. If you wish to place it earlier, you would need to establish the connection to the database manually.

Note that both methods cause persistent changes to the database, e.g. will remain after the tests have run. The changes only affect the database of which ever environment the code is run in e.g. test or development.

Related