gpt4 book ai didi

ruby-on-rails - mongoid 中具有 embeds_many 关联的 first_or_create 方法

转载 作者:可可西里 更新时间:2023-11-01 09:54:39 37 4
gpt4 key购买 nike

我有用于 omni-auth 身份验证的 User 模型。我已对其进行设置,以便可以使用不同的提供商(如 facebook、google 帐户)进行登录。如果在使用这些提供商注册时电子邮件已在数据库中,则用户已登录到该帐户。

类用户
包括 Mongoid::Document
embeds_many:供应商
字段:电子邮件,类型:字符串,默认值:“”
结尾
类提供者
包括 Mongoid::Document
字段:名称,类型:字符串
字段:uid,类型:字符串
嵌入_in:用户
结尾

我正在使用 from_omniauth 方法根据身份验证信息查找用户。

def from_omniauth(auth)
user=User.find_by(email: auth.info.email)
如果用户返回用户
where(:"providers.name"=> auth.provider, :"provider.uid"=> auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
结尾
结束

但是当它找不到用户并尝试创建一个用户时,我遇到了一个错误。Mongoid::Errors::UnknownAttribute:
信息:
试图为模型用户设置不允许的“providers.name”值。

但是为什么它认为这是动态字段生成,因为我已经定义了关联。我也尝试了 find_or_initialize 方法,但同样的错误。

谁能帮我弄清楚。提前致谢。

最佳答案

这里有一些魔法。

当您根据上述条件调用#first_or_create 时:

where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid ).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end

这实际上是被脱糖成更像这样的东西:

found_user_with_provider = where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid ).first
if found_user_with_provider.nil?
new_user = User.new
new_user.set(:"providers.name", auth.provider)
new_user.set(:"providers.uid", auth.uid)
new_user.email = auth.info.email
new_user.password = Devise.friendly_token[0,20]
else
found_user_with_provider.email = auth.info.email
found_user_with_provider.password = Devise.friendly_token[0,20]
end

注意尝试将“provider.name”和“provider.uid”的值设置为用户实例的属性 - 这实际上不是您想要的,而 Mongoid 正是提示。

你实际上可能想要更像这样的东西:

def from_omniauth(auth)
user = User.find_by(email: auth.info.email)
return user if user
found_user_with_provider = where(:"providers.name" => auth.provider, :"provider.uid" => auth.uid ).first
if found_user_with_provider
found_user_with_provider.update_attributes!(
:email => auth.info.email,
:password => Devise.friendly_token[0,20]
)
return found_user_with_provider
end
User.create!({
:providers => [
Provider.new({
:name => auth.provider,
:uid => auth.uid
})
],
:email => auth.info.email,
:password => Devise.friendly_token[0,20]
})
end

当然还有一个问题,那就是您要在您的用户实例上设置一个#password 属性。确保添加:

field :password,type: String, default: ""

对于您的用户模型 - 否则您会像以前一样收到关于动态字段的投诉 - 只是这次是关于不同的字段。

关于ruby-on-rails - mongoid 中具有 embeds_many 关联的 first_or_create 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37075602/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com