Garbar
7/18/2015 - 10:49 AM

20150402084453_create_identities.rb

# == Schema Information
#
# Table name: users
#
#  id                     :integer          not null, primary key
#  name                   :string
#  email                  :string           default(""), not null
#  encrypted_password     :string           default(""), not null
#  reset_password_token   :string
#  reset_password_sent_at :datetime
#  remember_created_at    :datetime
#  sign_in_count          :integer          default(0), not null
#  current_sign_in_at     :datetime
#  last_sign_in_at        :datetime
#  current_sign_in_ip     :inet
#  last_sign_in_ip        :inet
#  created_at             :datetime
#  updated_at             :datetime
#
class User < ActiveRecord::Base
  devise :database_authenticatable,
         :registerable,
         :recoverable,
         :rememberable,
         :trackable,
         :validatable,
         :omniauthable, omniauth_providers: [:google, :linkedin]

  has_many :identities

  def self.from_omniauth(auth)
    where(email: auth.info.email).first_or_create do |user|
      user.name = auth.info.name
      user.password = Devise.friendly_token[0,20]
    end
  end
end
Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end
# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  skip_before_filter :authenticate_user!

  %w(google linkedin).each do |provider|
    define_method provider do
      auth = request.env['omniauth.auth']
      unless identity = Identity.find_from_omniauth(auth)
        user = User.from_omniauth(auth)
        identity = Identity.create_from_omniauth(auth, user)
      end

      if identity.user.persisted?
        flash[:success] = 'Signed in successfully.'
        sign_in_and_redirect identity.user
      else
        redirect_to new_user_registration_url
      end
    end
  end

  def failure
    redirect_to root_path
  end
end
# == Schema Information
#
# Table name: identities
#
#  id         :integer          not null, primary key
#  provider   :string
#  uid        :string
#  user_id    :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
class Identity < ActiveRecord::Base
  belongs_to :user

  validates :provider, :user_id, :uid, presence: true

  def self.find_from_omniauth(auth)
    find_by(provider: auth.provider, uid: auth.uid)
  end

  def self.create_from_omniauth(auth, user)
    Identity.create!(user: user, provider: auth.provider, uid: auth.uid)
  end
end
# config/initializers/devise.rb
Devise.setup do |config|
  # ...
  
  config.omniauth :google_oauth2,
                  ENV['GOOGLE_CLIENT_ID'],
                  ENV['GOOGLE_CLIENT_SECRET'],
                  name: 'google'

  config.omniauth :linkedin,
                  ENV['LINKEDIN_KEY'],
                  ENV['LINKEDIN_SECRET'],
                  scope: 'r_basicprofile r_emailaddress',
                  secure_image_url: true
  
  # ...
end
/ app/views/layouts/_login_form.html.slim

/ with 'font-awesome-sass' gem
= link_to user_omniauth_authorize_path(:google), class: 'btn btn-block btn-social btn-google-plus' do
  = icon 'google-plus', 'Sign in with Google', class: 'fa-fw'

= link_to user_omniauth_authorize_path(:linkedin), class: 'btn btn-block btn-social btn-linkedin' do
  = icon 'linkedin', 'Sign in with LinkedIn', class: 'fa-fw'
source 'https://rubygems.org'

gem 'rails', '4.2.1'

gem 'devise'
gem 'omniauth-linkedin-oauth2'
gem 'omniauth-google-oauth2'
class CreateIdentities < ActiveRecord::Migration
  def change
    create_table :identities do |t|
      t.string :provider
      t.string :uid
      t.integer :user_id

      t.timestamps null: false
    end

    add_index :identities, :user_id
  end
end