开发者

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 }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜