Reputation: 464
I'm writing a down
method in my migration to deal with reverting a migration that replaces a string field with a reference field. Here's the code:
class ChangeCars < ActiveRecord::Migration[5.1]
def up
rename_column :cars, :make_id, :make_id_string
add_reference :cars, :make, foreign_key: true, optional: true
Cars.all.each do |car|
unless car.make_id_string.nil?
make = Make.find_by(uuid: car.uuid)
car.make_id = make
end
car.save!
end
remove_column :cars, :make_id_string
end
def down
add_column :cars, :make_id_string, :string
Cars.all.each do |car|
unless car.make.nil?
car.make_id_string = car.make.uuid
end
car.save!
end
# at this point :make_id_string -> String
remove_reference :cars, :make, index: true, foreign_key: true
rename_column :cars, :make_id_string, :make_id
# at this point :make_id -> Fixnum
end
end
It seems like when I'm removing the reference, I'm not completely flushing it out so when I replace the make_id
field, it takes on that fixnum
type.
Any suggestions are appreciated!
Upvotes: 1
Views: 142
Reputation: 23327
If you have real data in the make_id_string
I would strongly suggest not to remove it. If you have some bugs in the migration, it would save you. Also reverting the migration would be far easier.
If you want to iterate over all models in Car
, don't use #each
, because if loads all the cars to memory at once. Use #find_each
that loads records in batches.
Upvotes: 1