NoMethodError 未定义的方法“持续存在?” nil:NilClass 在通过 Omniauth/Devise 登录 Facebook 时?
NoMethodError undefined method `persisted?' for nil:NilClass when signing in with Facebook thru Omniauth/Devise?
我正在对 Rails 应用程序进行最后的润色,就在昨天,一切都运行良好(大部分仍然如此)。但是现在,当我尝试使用 Facebook 登录时出现错误 NoMethodError undefined method persisted? for nil:NilClass
我没有更改 omniauth_callbacks_controller 或用户模型中的任何代码,所以我不明白为什么会这样突然之间。
这是omniauth_callbacks_controller
中的代码
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
@user = User.from_omniauth(env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:twitter, :facebook].each do |provider|
provides_callback_for provider
end
并在 User.rb
def self.from_omniauth(auth)
identity = Identity.where(provider: auth.provider, uid: auth.uid).first_or_create do |identity|
if identity.user == nil
user = User.new
user.email = auth.info.email || "#{auth.uid}@#{auth.provider}.generated"
user.password = Devise.friendly_token[0,20]
user.provider = auth.provider
if auth.provider == "facebook"
user.name = auth.info.name
user.username = "FacebookUser" + (1 + rand(1000)).to_s
elsif auth.provider == "twitter"
user.name = auth.info.name
user.username = auth.info.nickname
end
end
identity.user = user
end
identity.access_token = auth['credentials']['token']
identity.refresh_token = auth['credentials']['refresh_token']
identity.expires_at = auth['credentials']['expires_at']
identity.timezone = auth['info']['timezone']
identity.save
identity.user
end
我不明白为什么它昨天能用,但现在不行了。什么也没有变!我仍然从同一个 URL 访问它,我没有弄乱 Facebook 或 devise.rb.
上的 API 设置
问题是 identity.user 是空的。这可能发生,因为用户无效(未保存在数据库中),在用户模型中未通过验证。
我认为问题可能出在 user.email = auth.info.email || "#{auth.uid}@#{auth.provider}.generated"
- 错误的电子邮件类型。您可以在创建用户的块中添加类似 puts user.errors
的内容。
另外我不明白你为什么需要一个模型 - 身份。更容易向用户模型添加字段
这是我的代码(有效):
def self.from_omniauth(auth)
email = auth.info.email
user = User.find_by(email: email) if email
user ||= User.create do |user|
user.provider= auth.provider
user.uid= auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name
user.email ||= "#{auth.uid}_#{auth.uid}@email.com"
end
end
我正在对 Rails 应用程序进行最后的润色,就在昨天,一切都运行良好(大部分仍然如此)。但是现在,当我尝试使用 Facebook 登录时出现错误 NoMethodError undefined method persisted? for nil:NilClass
我没有更改 omniauth_callbacks_controller 或用户模型中的任何代码,所以我不明白为什么会这样突然之间。
这是omniauth_callbacks_controller
中的代码def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
@user = User.from_omniauth(env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:twitter, :facebook].each do |provider|
provides_callback_for provider
end
并在 User.rb
def self.from_omniauth(auth)
identity = Identity.where(provider: auth.provider, uid: auth.uid).first_or_create do |identity|
if identity.user == nil
user = User.new
user.email = auth.info.email || "#{auth.uid}@#{auth.provider}.generated"
user.password = Devise.friendly_token[0,20]
user.provider = auth.provider
if auth.provider == "facebook"
user.name = auth.info.name
user.username = "FacebookUser" + (1 + rand(1000)).to_s
elsif auth.provider == "twitter"
user.name = auth.info.name
user.username = auth.info.nickname
end
end
identity.user = user
end
identity.access_token = auth['credentials']['token']
identity.refresh_token = auth['credentials']['refresh_token']
identity.expires_at = auth['credentials']['expires_at']
identity.timezone = auth['info']['timezone']
identity.save
identity.user
end
我不明白为什么它昨天能用,但现在不行了。什么也没有变!我仍然从同一个 URL 访问它,我没有弄乱 Facebook 或 devise.rb.
上的 API 设置问题是 identity.user 是空的。这可能发生,因为用户无效(未保存在数据库中),在用户模型中未通过验证。
我认为问题可能出在 user.email = auth.info.email || "#{auth.uid}@#{auth.provider}.generated"
- 错误的电子邮件类型。您可以在创建用户的块中添加类似 puts user.errors
的内容。
另外我不明白你为什么需要一个模型 - 身份。更容易向用户模型添加字段
这是我的代码(有效):
def self.from_omniauth(auth)
email = auth.info.email
user = User.find_by(email: email) if email
user ||= User.create do |user|
user.provider= auth.provider
user.uid= auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name
user.email ||= "#{auth.uid}_#{auth.uid}@email.com"
end
end