MySQL 5.7 began failing old migrations that set a default for columns of type text.
After editing the migration, dropping the development db and re-running all migrations, all worked fine in development.
For production:
1. Is my below understanding correct? Is this the main and/or only issue (besides editing old migrations being frowned upon)
The issue to look out for is that since you can't drop a production db, these migrations will not be run and not reflected in db/schema.rb
. As a result, your code will be error prone because it was written to work with a slightly different schema in development.
2. My solution is to essentially force the migration to re-run by calling its up
method in a new migration. (See below code). Is this a reasonable solution? ie. Will it work in all cases (no critical downfalls).
This is the original migration, made years ago in Rails 2
class AddZipWarpableResHistory < ActiveRecord::Migration[5.2]
def self.up
add_column :warpables, :history, :text, :default => "", :null => false
add_column :warpables, :cm_per_pixel, :float, :default => 0, :null => false
Warpable.find(:all).each do |w|
r = w.get_cm_per_pixel
w.cm_per_pixel = r if r != nil
w.save
end
end
def self.down
remove_column :warpables, :history
remove_column :warpables, :cm_per_pixel
end
end
after edits (only including the edited lines below) in Rails 5
class AddZipWarpableResHistory < ActiveRecord::Migration[5.2]
def self.up
add_column :warpables, :history, :text, :null => false
Warpable.all.each do |w| # edited this bc find(:all) was broken as well
r = w.get_cm_per_pixel
w.cm_per_pixel = r if r != nil
w.save
end
end
end
new migration to ensure it works in production:
- Note that none of the changes in that migration have any subsequent changes in other migrations before this one to account for
require_relative '20111005211631_add_zip_warpable_res_history'
class EnsureNoWarpableCorruption < ActiveRecord::Migration[5.2]
def self.up
AddZipWarpableResHistory.down
AddZipWarpableResHistory.up
msg = 'MySQL 5.7 began throwing errors on migrations that set a default for columns of type text.' +
'We edited that migration and rerun it here to ensure no data corruption in production'
change_table_comment(:warpables, msg)
end
def self.down
raise ActiveRecord::IrreversibleMigration
end
end
- Would just editing the production DB manually in MySQL before merging this be an alternative solution if the model code wasn't updated as well?
- MySQL doesn't support transactional migrations. Is this the simple solution when working with other databases?
Notes
I didn't execute SQL directly because then we would probably need to start storing
db/structure.sql
instead ofdb/schema.rb
.I didn't try to fix any model code or other logic.