Rails 上的 Ruby / ActiveRecord:使用 first_or_initialize 更新记录会导致 RecordNotUnique

Ruby on Rails / ActiveRecord: Updating records with first_or_initialize causes RecordNotUnique

我目前正在从 SAML 断言中获取用户数据,并根据该信息在本地数据库中创建用户:

mapped_role = map_role user_role
user = User.where(email: auth_attrs.single('Email')).first_or_initialize do |u|
  u.firstname = auth_attrs.single('First Name')
  u.uid = auth_attrs.single('UID')
  u.provider = resp.provider
  u.role = mapped_role
 end

这很好用,但是当用户的详细信息发生变化时(例如,他们的角色发生变化),数据库中的数据不会得到更新。我尝试做的是将角色分配移出 do 块(在 first_or_initialize 返回的 user 对象上),然后调用后续操作 user.save,但这会导致一个漂亮的红色屏幕,通知我 'email' 列不是唯一的。我不想在这里创建新记录,只是更新现有记录。这里有更好的模式吗?

编辑:我尝试了 here 中列出的各种方法,但它们会导致相同的 SQLite3 错误。好像我在那里遗漏了什么。

Edit2:看起来这可能是因为 Devise 试图用它自己的电子邮件字段在幕后做一些事情(?)。

我想我会这样做

mapped_role = map_role user_role
# find the user or initatiate an new un-persisted user
user = User.find_or_initialize_by(email: auth_attrs.single('Email'))
attributes = {firstname: auth_attrs.single('First Name'), 
              uid: auth_attrs.single('UID'), 
              provider: resp.provider, 
              role: mapped_role}
# attempt to update the above record with the appropriate attributes 
# this will set the attributes and fire #save
if user.update(attributes)
  # successful
else
  # handle validation errors 
end

这样就不需要对已经存在的用户和新用户进行逻辑处理。