当我第一次实施用户模型时,我允许用户输入大写或小写电子邮件以获取其登录信息。问题是它是一个移动应用程序,有时会发生自动缓存,因此用户无法进行身份验证。我已经将CREATE方法更改为首先将电子邮件设置为小写。但是,这会导致现有帐户的人不一致
那么如何添加迁移以批量更新users表中的电子邮件字段以使其缩写呢?
答案 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
Postgres和MySQL都支持LOWER
功能。 SQLite也支持它,但仅适用于ascii编码,这可能适用于电子邮件,但可能会导致错误(因为某些电子邮件可能包含其他字符)。 Rails还可能支持任意数量的数据库,因此依靠这些功能可以使您的应用程序锁定到特定的数据库。
答案 3 :(得分:3)
永远不要担心优化您只会做一次的事情。除非您拥有大量用户,否则只需使用您最熟悉的方法。 (虽然我建议只运行SQL查询。)
答案 4 :(得分:0)
以下是最简单的解决方案,而不是进行迭代:
ActiveRecord::Base.connection.execute "UPDATE users SET email = LOWER(email)"