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

JBl*_*ake 11 ruby database activerecord ruby-on-rails

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

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

ctc*_*rry 24

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

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

execute("UPDATE users SET email = LOWER(email)")
Run Code Online (Sandbox Code Playgroud)


小智 9

你可以简单地去

User.update_all('email = lower(email)')
Run Code Online (Sandbox Code Playgroud)


Jak*_*mpl 7

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

class DowncaseEmail < ActiveRecord::Migration
  def up
    User.all.each do |user|
      user.update_attributes :email => user.email.downcase
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

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

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

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
Run Code Online (Sandbox Code Playgroud)

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