I am putting the finishing touches on a Rails app, and everything was working fine just yesterday, (most of it still is). But now, when I try to sign in with Facebook I get the error NoMethodError undefined method persisted? for nil:NilClass
I haven't changed any code in the omniauth_callbacks_controller, or in the User Model, so I do not understand why this is happening all of the sudden.
Here's the code in 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
And in 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
I cannot figure out why it WAS working yesterday, but now it's not. Nothing has changed! I'm still accessing it from the same URL, I haven't messed with the API settings on Facebook, or in devise.rb.
the problem is that identity.user is nill. It could happen, because user not valid(not saved in db), in user model did not pass validations.
I think problem can be in user.email = auth.info.email || "#{auth.uid}@#{auth.provider}.generated"
- wrong email type. You can add something like puts user.errors
in block wehe you created user.
Also i don't understand why you need a model - identity. Much easier add field to user model
Here is my code(it's work):
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