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)
end end

写完 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)
    ...
  end

end

方法写好了,以前的代码调用 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. 偷懒须谨慎

原文地址:https://www.cnblogs.com/laoquans/p/3982834.html