rails migration version compatibility
Here is the scenario
production/staging code is on version X
Version X of code
# order model
class Order < ActiveRecord::Base
has_many :payment_transactions
# has column for check_number
def update_report
ReportTable.where(:order_id => id).first.update_attributes(:check_number => check_number)
end
end
# payment_transaction model
class PaymentTransaction < ActiveRecord::Base
end
Version X + 5 of code
# migration
Order.all.map{|x| x.update_report }
Version X + 10 of code (current)
# migration
add_column :payment_transactions, :check_number, :integer
# order model
class Order < ActiveRecord::Base
has_many :payment_transactions
# moved the column check_number to payment_transactions
def check_number
self.payment_transactions.where(:method => 'check').blank? ? nil : self.payment_transactions.where(:method => 'check').first.check_number
end
def update_report
ReportTable.where(:order_id => id).first.update_attributes(:check_number => check_number)
end
end
# payment_transaction model
class PaymentTransaction < ActiveRecord::Base
# has column for check_number
end
Now when i update the code on staging environment to the latest version (X+10) and run migration, the migration on X+5 fails because it tries to run this
def check_number
self.payment_transactions.where(:method => 'check').blank? ? nil : self.payment_transactions.where(:method => 'check').first.check_number
end
and payment_transaction will 开发者_运维知识库not get check_number field until X+10 migration.
Whats the best way to handle this?
I would comment the update_report
call on the X+5 migration, run it, then run the snippet on rails console after I'm done.
Or change the migration to perform a direct SQL query:
execute "update report_tables set check_number = x.check_number ...."
If you can't avoid the models in the migration then, change the X+5 migration to:
Order.all.each do |o|
ReportTable.where(:order_id => o.id).first.update_attributes(:check_number => o.check_number)
end
This will continue to reference the order's check number attribute which should still be there at that time.
I ended up moving the this code form migration in X+5
Order.all.map{|x| x.update_report }
to migration in X+10
# migration
add_column :payment_transactions, :check_number, :integer
Order.all.map{|x| x.update_report }
精彩评论