首页 > 代码库 > rails migrate 同名的问题, 当为了图省事的时候,问题就会找上门
rails migrate 同名的问题, 当为了图省事的时候,问题就会找上门
users 表结构 ( name, address )
现要让 users 表添加多个地址,于是乎有了下面的 migration
def change unless column_exists? :users, :address_id add_column :users, :address_id, :string User.all.each do |user| if user.address.present? address = Address.create( name: user.address, user_id: user.id ) user.update_column(:address_id, address.id) end end remove_column(:users, address)
endend
写完 migration , 运行,查看数据库,一切正常。需求继续做下去。由于原本的代码 user 对象有 address 这个属性,并且在许多地方都用到了这个属性,现在这个属性没有了,于是乎,为了方便我便给写了两个同名的方法.
class User < ActiveRecord::Base def address address = Address.find(address_id) rescue nil return address == nil ? "" : address.name end def address=(addr) ... endend
方法写好了,以前的代码调用 address , 功能也正常。省去了很多事情。
git 提交需求,建 merger request . 项目经理看了后,没什么问题,也给合并了。 项目经理运行 migrate 之后,发现该功能上线之后,用户的地址都不见了。而我本地是好的阿,而服务器上,后来创建的数据也存在,而之前用户的地址没有保存下来。项目经理查看数据库,乖乖,之前的用户 address 数据都丢失了。
坏事了, migrate 有问题,看migrate 好像也没有问题阿。仔细想了想,哦,已经来不及半点的后悔。
问题在于 User 类里面的 address 方法, 在本地开发的时候 当运行 migrate 的时候,User 类里面还没有 address 方法, 所以一切正常。当合并之后运行 migrate的时候,是有 address 这个方法的。所以 migrate 里面那个if 都不执行,而在最后又执行了 remove_column , 导致数据丢失。
后来就被项目经理讲了一顿, 也从项目经理那学到了,类似的情况该如何处理。
总结:
1. 数据在进行 migrate 的时候,是很有可能出现问题的。并且有些问题是你很难考虑周全的,人都有疏忽的时候, 犯错误在所难免。
2. 在写 migrate 的时候,特别是删除列、数据 这样的操作,一定要千万小心,不能有半点的自信。
3. 以后写 migrate 的时候,能不用删除数据,就不要删。类似于这样需要删除的情况,可以把当前的列重命名保存起来。等新的表结构确实没有问题的时候(通常是过一段时间的考验)。再删除这些数据不迟。
4. 偷懒须谨慎
rails migrate 同名的问题, 当为了图省事的时候,问题就会找上门