NoMethodError未定义的方法`持久化?' nil:通过Omniauth / Devise与Facebook签约时的NilClass?

时间:2016-04-17 06:56:41

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

我正在对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上的API设置或devise.rb。

1 个答案:

答案 0 :(得分:0)

问题是identity.user是nill。可能会发生这种情况,因为用户模型中的用户无效(未保存在db中),未通过验证 我认为问题可以在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