我正在编写一个大型迁移脚本,并遇到了一个重大问题。
# Import users
user_data.each do |data|
u = User.new
u.id = data.id
u.email = data.email
# more user attributes set...
u.save!
end
# required to prevent Postgres from trying to use now taken user ids
ActiveRecord::Base.connection.execute "ALTER SEQUENCE users_id_seq RESTART WITH #{User.last.id+1};"
首先,我们从数据源读取用户数据,并手动设置它的id。我们需要保留ID,因为我们也在迁移相关数据。
然后,我们需要从关联对象的数据中有条件地创建更多用户。
# Create a user for this email if no user with this email exists.
if data.email
user = User.find_by_email(data.email)
if user
o.user = user
else
o.user = User.create!(
first_name: 'Unknown',
last_name: 'Unknown',
email: data.email,
password: generate_temp_password
)
end
end
这在User.create!
处失败:
Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)
我已经调试了一下,可以在抛出此错误之前看到User.where(email: data.email).first
是nil
。我怀疑这与设置id超出当前自动增量值有关,以某种方式导致新记录在我的查询中不可见,但Postgres自己的验证可见。
那么具有特定电子邮件的用户如何不存在,但仍会触发数据库验证错误?
答案 0 :(得分:1)
显然,Devise下调了电子邮件地址。违规电子邮件中有一些上限。所以它错过了区分大小写的检查,然后在不区分大小写时作为欺骗失败。
设计似乎超出了我的范围。