Search code examples
ruby-on-railspostgresqlomniauthrails-postgresql

Rails - Generate email address when one doesn't exist with Omniauth integration


I am working with omniauth with Rails and trying to get twitter, facebook and google hooked up for authentication but keep running into this error:

PG::Error: ERROR:  duplicate key value violates unique constraint "index_users_on_email"
DETAIL:  Key (email)=() already exists.

Here is my Authentication Controller:

class AuthorizationsController < ApplicationController


      def create
        authentication = Authorization.find_by_provider_and_uid(auth['provider'], auth['uid'])

        if authentication
          flash[:notice] = "Signed In Successfully"
          sign_in authentication.user, event: :authentication
          redirect_to root_path
        else
          athlete = Athlete.new
          athlete.apply_omniauth(auth)

          debugger

          if athlete.save(validate: false)
            flash[:notice] = "Account created and signed in successfully"
            sign_in athlete, event: :authentication
            redirect_to finalize_profile_path
          else
            flash[:error] = "An error has occurred. Please try again."
            redirect_to root_path
          end
        end
      end

      def failure
        render json: params.to_json
      end

      private

        def auth
          request.env["omniauth.auth"]
        end

        def resource(user_type)
          user_type.downcase.to_sym
        end

    end

I think what is happening is that when the Athlete is created it is creating one with a blank email address and the unique key is failing... how could I get around this? I think I know how to fix this for Google integration but since Twitter doesn't return an email, this issue will not resolve itself


Solution

  • This is how I was able to get it working:

    class AuthorizationsController < ApplicationController
    
      def create
        authentication = Authorization.find_by_provider_and_uid(auth['provider'], auth['uid'])
    
        if authentication
          flash[:notice] = "Signed In Successfully"
          sign_in authentication.user, event: :authentication
          redirect_to root_path
        else
          athlete = Athlete.new(email: generate_auth_email(params[:provider]) )
          athlete.apply_omniauth(auth)
    
          debugger
    
          if athlete.save(validate: false)
            flash[:notice] = "Account created and signed in successfully"
            sign_in athlete, event: :authentication
            redirect_to finalize_profile_path
          else
            flash[:error] = "An error has occurred. Please try again."
            redirect_to root_path
          end
        end
      end
    
      def failure
        render json: params.to_json
      end
    
      private
    
        def auth
          request.env["omniauth.auth"]
        end
    
        def resource(user_type)
          user_type.downcase.to_sym
        end
    
        def generate_auth_email(provider)
          return auth.info.try(:email) unless provider == "twitter"
          return "#{auth.uid}@twitter.com" if provider == "twitter"
        end
    
    end
    

    I create an email using the twitter uid with twitter.com being the domain since twitter does not return an email address

    Hope this helps someone in the future