【问题标题】:Ruby on Rails / ActiveRecord: Updating records with first_or_initialize causes RecordNotUniqueRuby on Rails / ActiveRecord:使用 first_or_initialize 更新记录会导致 RecordNotUnique
【发布时间】:2018-04-11 21:46:52
【问题描述】:

我目前正在从 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,但这会导致一个非常红的屏幕通知我“电子邮件”列不是唯一的。我不想在这里创建新记录,只是更新现有记录。有没有更好的模式可以在这里使用?

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

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

【问题讨论】:

    标签: ruby-on-rails ruby activerecord devise omniauth


    【解决方案1】:

    我想我会这样去做

    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
    

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

    【讨论】:

    • 我将把它标记为正确,因为它解决了所提出的问题。我认为我的问题最终与设计干扰我的用户表并造成严重破坏有关。
    猜你喜欢
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多