为轨道中的所有记录批量填写字段

时间:2011-03-12 22:57:45

标签: ruby-on-rails ruby database activerecord

当我第一次实施用户模型时,我允许用户输入大写或小写电子邮件以获取其登录信息。问题是它是一个移动应用程序,有时会发生自动缓存,因此用户无法进行身份验证。我已经将CREATE方法更改为首先将电子邮件设置为小写。但是,这会导致现有帐户的人不一致

那么如何添加迁移以批量更新users表中的电子邮件字段以使其缩写呢?

5 个答案:

答案 0 :(得分:23)

最有效的方法是避免使用Ruby迭代器,并直接在SQL中执行。

在普通迁移文件中,您可以将此SQL用于MySQL:

execute("UPDATE users SET email = LOWER(email)")

答案 1 :(得分:7)

您可以简单地使用

User.update_all('email = lower(email)')

答案 2 :(得分:6)

最简单的解决方案是使用Ruby代码:

class DowncaseEmail < ActiveRecord::Migration
  def up
    User.all.each do |user|
      user.update_attributes :email => user.email.downcase
    end
  end
end

正如其他人所说,这不是最有效的解决方案。我倾向于选择可移植性而不是性能,但这取决于我们所谈论的记录数量。

更复杂但仍可移植的解决方案取决于某些特定于数据库的功能:

class DowncaseEmail < ActiveRecord::Migration
  def up
    if %w[MySQL PostgreSQL].include? ActiveRecord::Base.connection.adapter_name
      execute "UPDATE users SET email = LOWER(email)"
    else
      User.all.each do |user|
        user.update_attributes email: user.email.downcase
      end
    end
  end
end

PostgresMySQL都支持LOWER功能。 SQLite也支持它,但仅适用于ascii编码,这可能适用于电子邮件,但可能会导致错误(因为某些电子邮件可能包含其他字符)。 Rails还可能支持任意数量的数据库,因此依靠这些功能可以使您的应用程序锁定到特定的数据库。

答案 3 :(得分:3)

永远不要担心优化您只会做一次的事情。除非您拥有大量用户,否则只需使用您最熟悉的方法。 (虽然我建议只运行SQL查询。)

答案 4 :(得分:0)

以下是最简单的解决方案,而不是进行迭代:

ActiveRecord::Base.connection.execute "UPDATE users SET email = LOWER(email)"