可以使用Rails迁移来转换数据吗?

Kir*_*ein 32 ruby migration ruby-on-rails

我正在尝试在我的Rails应用程序中转换一个列,为了参数,让我假装我试图将age我的users表中的列更改为字符串表示而不是int.

在我的迁移中我有这个;

def.self up
    add_column :users, :age_text, :string

    users = User.find(:all)

    users.each do |u|
       u.age_text = convert_to_text(u.age)
       u.save
    end
end

def self.convert_to_text(number)
   #code here to convert 1 to 'one' etc
end
Run Code Online (Sandbox Code Playgroud)

但它似乎没有起作用,我在这里尝试甚至可以进行迁移吗?

Edu*_*coz 58

你想做的事情是可能的,我会说正确的事情.

但是,您需要重新加载要在迁移中更新的模型类的列信息,以便Rails了解新列.试试这个:

def.self up
    add_column :users, :age_text, :string

    User.reset_column_information 

    users = User.find(:all)

    users.each do |u|
       u.age_text = convert_to_text(u.age)
       u.save
    end
end
Run Code Online (Sandbox Code Playgroud)

另请注意,如果您的桌子很大,逐个更新需要花费很长时间.请注意.

  • 什么是更好的方式? (2认同)
  • 对于大型表,您可以使用批量作业http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects-in-batches (2认同)

Bri*_*gan 39

由于我是新来的,我无法对上述内容发表评论,因此我将添加自己的答案.

通常在迁移中操纵数据是一个不好的想法.如果模型逻辑发生变化,直接模型访问的迁移可能会卡住.

想象一下,在第二次迁移中,您添加了一个新列.您希望使用新数据为该列添加种子.

我们还要说几周之后,您会为模型添加一个新的验证 - 对第二次迁移中尚不存在的字段进行验证.如果您曾经从迁移0构建数据库,那么您会遇到一些问题.

我强烈建议使用迁移来更改列和其他方法来管理数据库数据,尤其是在转移到生产时.

  • 这种情况不太可能发生.您通常在完成所有迁移后运行rake任务,并且通常不会在具有实际数据的数据库上重新运行迁移.一旦你"修复"了你的数据,你就不需要再回到0来修复它.鼓励新开发人员和新生产箱使用rake db:schema:load来创建数据库,这样很快,并立即构建最新的数据库.对我来说,数据转换是"一次性"的事情.您转换数据并继续前进. (10认同)
  • 有没有办法确保您的rake任务以正确的顺序运行,然后进行迁移?如果在此之后进行的迁移然后在运行rake任务之前删除了过时的列,该怎么办? (3认同)
  • 我认为迁移是发生这种情况的适当位置,但为了做到正确,你需要一个git钩子,对于每个版本,将应用更改,然后运行`bundle exec rake db:migrate`,然后转移到下一个修订.也许我们会看到这个与git的集成最终内置到rake/rails/heroku/etc中. (3认同)