显式设置ID时的数据迁移问题(Rails + Postgres)

时间:2013-09-12 01:36:30

标签: ruby-on-rails ruby postgresql migration

我正在编写一个大型迁移脚本,并遇到了一个重大问题。

# 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).firstnil。我怀疑这与设置id超出当前自动增量值有关,以某种方式导致新记录在我的查询中不可见,但Postgres自己的验证可见。

那么具有特定电子邮件的用户如何不存在,但仍会触发数据库验证错误?

1 个答案:

答案 0 :(得分:1)

显然,Devise下调了电子邮件地址。违规电子邮件中有一些上限。所以它错过了区分大小写的检查,然后在不区分大小写时作为欺骗失败。

设计似乎超出了我的范围。