Matteo Pagliazzi
Matteo Pagliazzi

Reputation: 5270

Devise, Omniauth and 'new with session'

I have a method in my user model (which uses devise and confirmable) called new_with_session as required by Omniauth + Devise (https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview):

def self.new_with_session(params, session)
  super.tap do |user|
    if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] || session["devise.google_data"] && session["devise.google_data"]["extra"]["raw_info"]
      user.email = data["email"]
    end
  end
end

Users are allowed to sign in using either Google or Facebook, and I'm using this line to save the right user.email:

if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] || session["devise.google_data"] && session["devise.google_data"]["extra"]["raw_info"]

but I don't think is the right way, so...

  1. Do you know a better way to build user.email than using the || operator?
  2. If I want to save some more data from Google/Facebook, like the username, should I add it to my custom new_with_session? If so, why?

Upvotes: 3

Views: 4738

Answers (2)

namor
namor

Reputation: 106

new_with_session is used in build_resource. This is used with registerable (user regsitration forms).

This is only useful when your Facebook/Omniauth session already exists and you want to prefill your Registration form with some data from omniauth. (assuming you didn't already create the account automatically on callback)

# Build a devise resource passing in the session. Useful to move
# temporary session data to the newly created user.
def build_resource(hash=nil)
  hash ||= params[resource_name] || {}
  self.resource = resource_class.new_with_session(hash, session)
end

Upvotes: 9

Eric K
Eric K

Reputation: 395

Are you looking to authenticate an existing account in your system via Facebook or Gmail, using the email address as the identifier, and create an account with that email address if it doesn't already exist? If so, I don't think you need to use new_with_session; you can use a model method as described in that link you cited:

def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
  data = access_token.extra.raw_info
  if user = User.where(:email => data.email).first
    user
  else # Create a user with a stub password. 
    User.create!(:email => data.email, :password => Devise.friendly_token[0,20]) 
  end
end

You can create a similar self.find_for_google_oauth method, and a corresponding google method in your Users::OmniauthCallbacksController.

If you want to use additional data from the Facebook or Google callback, when creating the user, you can just add it to the User.create! line in your find_for_oauth methods, like so:

User.create!(:email => data.email, 
  :first_name => data.first_name, 
  :last_name => data.last_name, 
  :password => Devise.friendly_token[0,20])

This worked fine for me, and I didn't need to do anything with new_with_session. I'm still learning Devise and OmniAuth, however, so if there's something wrong with this approach, I'd love to hear about it.

Upvotes: 1

Related Questions