简体   繁体   English

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

[英]Mass downcase a field for all records in rails

When I first implemented a User model , I allowed the user to type upper or lowercase email for their login info. 当我第一次实现User模型时,我允许用户输入大写或小写的电子邮件来获取他们的登录信息。 The problem is that its a mobile app, and sometimes autocaps happen so the user would not get authenticated. 问题是它是一个移动应用程序,有时会发生自动缓存,因此用户无法进行身份验证。 I've changed the CREATE method to downcase the email first. 我已经将CREATE方法更改为首先将电子邮件设置为小写。 However, this causes people with existing accounts to not be consistent 但是,这会导致现有帐户的人员不一致

So how can I add a migration to mass update the email field in the users table to downcase it? 那么如何添加迁移以批量更新users表中的电子邮件字段以使其缩写呢?

The most efficient way would be to avoid using a Ruby iterator, and do it directly in SQL. 最有效的方法是避免使用Ruby迭代器,并直接在SQL中执行。

Inside of a normal migration file you can use this SQL for MySQL: 在普通迁移文件中,您可以使用此SQL for MySQL:

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

你可以简单地去

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

The simplest solution is to just use Ruby code: 最简单的解决方案是使用Ruby代码:

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

As others have noted, this is not the most efficient solution. 正如其他人所指出的,这不是最有效的解决方案。 I tend to prefer portability over performance, but that depends on the number of records we are talking about. 我倾向于选择可移植性而不是性能,但这取决于我们所谈论的记录数量。

A more complex but still portable solution depends on some db specific functions: 更复杂但仍可移植的解决方案取决于某些特定于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

Both Postgres and MySQL support the LOWER function. PostgresMySQL都支持LOWER功能。 SQLite also supports it, but only for ascii encoding which is probably fine for emails, but might cause bugs (since some emails may contain other characters). SQLite也支持它,但仅适用于ascii编码,这可能适用于电子邮件,但可能会导致错误(因为某些电子邮件可能包含其他字符)。 Rails also potentially supports any number of databases, so relying on these functions can make your app locked in to a specific DB. Rails还可能支持任意数量的数据库,因此依赖这些功能可以使您的应用程序锁定到特定的数据库。

Never worry about optimizing something that you're only going to do once. 永远不要担心优化你只会做一次的事情。 Unless you have massive numbers of users, just use the methodology that will be most familiar to you. 除非您拥有大量用户,否则只需使用您最熟悉的方法。 (Though I would recommend just running the SQL query.) (虽然我建议只运行SQL查询。)

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM