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