1

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

# 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 自己的验证可见。

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

4

1 回答 1

1

显然,Devise 会降低电子邮件地址的大小写。有问题的电子邮件中有一些上限。所以它错过了一个区分大小写的检查,然后在不区分大小写时作为一个骗子失败了。

设计似乎比我聪明。

于 2013-09-12T18:33:02.080 回答