时间:2021-07-01 10:21:17 帮助过:44人阅读
最近在rails3.2下修改数据库表的字段,然后想回滚取消操作,但是在执行rake db:rollback命令时,出现错误: rake aborted!An error has occurred, all later migrations canceled:ActiveRecord::IrreversibleMigration/usr/local/rvm/gems/ruby-1.9.3-p392/ge
最近在rails3.2下修改数据库表的字段,然后想回滚取消操作,但是在执行rake db:rollback命令时,出现错误:rake aborted! An error has occurred, all later migrations canceled: ActiveRecord::IrreversibleMigration/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.14/lib/active_record/migration/command_recorder.rb:42:in `block in inverse'
我的migration内容如下:
class ChangeVmTempColumns < ActiveRecord::Migration def change change_table :vm_temps do |t| t.change :disksize, :integer, :limit => 8 t.change :mem_total, :integer, :limit => 8 end end end
上网查了资料,貌似原因在于如果在migration中做的数据类型转换是破坏性的时,就不能完成回滚。也就是说,对数据库表的字段类型进行修改时,数据库中的数据也会有变化,这样不能回滚这些变动的数据。
《The migration that cannot be undone: Irreversible Migration》文章中举了一个例子:当我们在migration中change_column由integer变为string时是可以的,但是如果反过来,字段类型由string变为integer,我们就不能reverse this migration。正好和我这种情况一致!
Stackoverflow上,这个问题《ActiveRecord::IrreversibleMigration exception when reverting migration》提供了一个解决办法:把self.change改为self.up和self.down方法。
修改后的migration:
class ChangeVmTempColumns < ActiveRecord::Migration def self.up change_table :vm_temps do |t| t.change :disksize, :integer, :limit => 8 t.change :mem_total, :integer, :limit => 8 end end def self.up change_table :vm_temps do |t| t.change :disksize, :string t.change :mem_total, :string end end end
执行rake db:rollback,成功!
原因:我原来认为在Rails中,self.change方法直接把self.up和self.down两个综合在一起,执行和回滚只用一个change方法就可以,但是经过这个例子,我认为self.change方法执行回滚时,只能采用默认的方式执行,一旦出现上述类型转换的问题就无法正常执行;但是self.down方法执行回滚时,会强制执行self.down中的语句,这样就不会出现irreversible migration的错误。