在Migration中操作新添加的字段

在有些情况下,我们需要在某个migration中对新增加的字段进行操作,比如下面这个将name改成first_name和last_name的migration:


def self.up
  add_column :profiles, :last_name, :string
  add_column :profiles, :first_name, :string
  Profile.find(:all).each do |profile|
    profile.first_name = profile.name
    profile.save(false)
  end
  remove_column :profiles, :name
end

这段代码看起来没什么问题,但是如果你真的这么做,那就惨了,你数据库中所有用户的名字信息都会丢失,而不会如你所愿的保存到first_name中,这是因为,当你为profiles表添加first_name字段时,Profile model已经完成了初始化,因此在它的columns里面是不存在first_name的,自己它也就不会被保存到数据库中,因此,要使上面这段代码工作正常,你需要在修改数据库后重新加载Profile model:


def self.up
  add_column :profiles, :last_name, :string
  add_column :profiles, :first_name, :string
  Profile.remove_class(Profile)
  load('profile.rb')
  Profile.find(:all).each do |profile|
    profile.first_name = profile.name
    profile.save(false)
  end
  remove_column :profiles, :name
end

现在,name就可以被正确的迁移到first_name字段中了,这个方法也可以用于在Console中重新加载某个过期的model。

This entry was posted in 其它. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • leondu

    其实我觉得数据操作放在migration里面不合适,migration关注数据结构的操作,而不是数据的操作。

    数据操作用rake task来做更加合适。

  • yuanyi

    我也认为Migration不应该操作数据,但有些情况下在Migration里直接操作会简单一些,尤其是涉及到部署的时候

  • sean

    数据库中所有用户的名字信息不会丢失吧?在调用”remove_column :profiles, :name”之前,migration 会因为找不到first_name方法退出.

    用Profile.reset_column_information也可以的.

  • Yuanyi

    我用2.0.2,不会提示出错,但是first_name得不到保存,然后name就被删了。

    reset_column_information比较有用

无觅相关文章插件,快速提升流量