如果该模型没有列值,请向postgres列添加值

时间:2014-09-22 19:37:55

标签: ruby-on-rails postgresql activerecord ruby-on-rails-4 rails-activerecord

我需要浏览所有当前用户模型并检查属性new_attribute是否有值,如果有,那么我想保留它,如果没有那么我想给它一个值。

以此为例。如果用户模型在其学校列中有值,那么它将保留,但如果它没有值,那么它将被赋予值"无"。

这是我应该在迁移中做些什么吗?我该如何编写迁移?

2 个答案:

答案 0 :(得分:0)

您应该编写迁移。有两种方法可以编写迁移。

执行直接查询

def up
  execute("update users set school='None' where school is null")
end

def down
  raise ActiveRecord::IrreversibleMigration
end

使用ActiveRecord

def up
  User.where("school is null").update_all(school: 'None')
end

def down
  raise ActiveRecord::IrreversibleMigration
end

答案 1 :(得分:0)

迁移通常最适合数据库架构更改。

来自docs(强调我的):

  

迁移是一种以一致且简单的方式随时间改变数据库架构的便捷方式。 ...您可以将每次迁移视为数据库的新“版本”。

这没有提到数据更新。只有架构更改。

他们很容易对数据存储的数据造成严重破坏。加分是这是一个单向保险丝。一旦在数据库上运行,此迁移将永远不会再次运行。

但是,更好的想法可能是创建一个幂等的rake任务来完成相同的数据迁移。

让我们稍微改变一下我们对这个问题的看法。也许我们只能找到没有学校信息的用户。然后我们只需要检索和更新这些用户。我们可以忽略所有其他用户。

示例rake任务是(假设用户有一个id字段):

namespace :remove_nulls_from_user_schools do
  User.where(school: nil).each do |user|
    user.school = 'None'
    if user.save
      puts "Updated school for user with id: #{user.id}"
    else
      puts "Update Failed for user with id: #{user.id}"
    end
  end
end

这个rake任务具有可重新运行的额外好处(但是,它不是精确幂等的)。如果使用空的学校字段生成更多用户,则可以重新运行此rake任务并修复任何新用户。

根据您要更新的用户数量,您可能希望使用User.find_each之类的内容来迭代用户。

如果要更新大量用户,还可以使用rake任务中提供的先前答案的sql。这将是一个非常快速的rake任务,可以实现同样的目标:

namespace :remove_nulls_from_user_schools do
  ActiveRecord::Base.connection.execute('update users set school='None' where school is null')
end

有关执行原始sql的更多信息,请参阅Rails 3 execute custom sql query without a model