Mita Das
Mita Das

Reputation: 43

ruby on Rails make unique Profile for a User

I have two models one user and other is profile

class User < ActiveRecord::Base
   has_one :profile
   delegate :first_name, :last_name, :email, :phone, :location, to: :profile
end


class Profile < ActiveRecord::Base
  belongs_to :user
end

How can I validate user profile uniqueness as everytime for a same user it create many profiles after user signout and again signin by omniauth

like below

def self.from_omniauth(auth)
      where(auth.slice(:provider, :uid).permit!).first_or_initialize.tap do |user|
        user.provider = auth.provider
        user.uid = auth.uid
        user.name = auth.info.name
        user.oauth_token = auth.credentials.token
        user.refresh_token = auth.credentials.refresh_token


        user.build_profile(first_name: auth.info.first_name, last_name: auth.info.last_name, email: auth.info.email, location: auth.info.location, phone: auth.info.phone)
        user.save!
      end
    end

how to make unique priofile for a uniq user .

One way I did it

 def self.from_omniauth(auth)
      where(auth.slice(:provider, :uid).permit!).first_or_initialize.tap do |user|
        user.provider = auth.provider
        user.uid = auth.uid
        user.name = auth.info.name
        user.oauth_token = auth.credentials.token
        user.refresh_token = auth.credentials.refresh_token
        user.auth_token = auth.credentials.token
        user.instance_url = auth.credentials.instance_url
        user.save!
        if Profile.exists?(email: auth.info.email)
          user.profile = Profile.where(email: auth.info.email).first
          user.save
        else    
          user.build_profile(first_name: auth.info.first_name, last_name: auth.info.last_name,\
         email: auth.info.email, location: auth.info.location, phone: auth.info.phone).save
        end   
      end
    end

but it is not a good way

I know it is very basic but want a best way..

Thanks in advance

Upvotes: 1

Views: 115

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

You're getting confused between business logic and data integrity.

--

Your model (db) structure should be such that each user should have one profile. It doesn't matter if that user is logged in, eating curry or doing his laundry; he still has one profile:

#app/models/user.rb
class User < ActiveRecord::Base
   has_one :profile
   accepts_nested_attributes_for :profile

   before_create :build_profile
end

#app/models/profile.rb
class Profile < ActiveRecord::Base
   belongs_to :user
end 

The above creates a new profile when the user object is created. You already kind of have this functionality with your existing code.

The difference is that the above creates the data structure, which you can apply business logic to afterwards.

What you do with that data (business logic) is delegated from the fact each user has one profile:

def self.from_omniauth(auth)
      where(auth.slice(:provider, :uid).permit!).first_or_initialize.tap do |user|
        user.provider = auth.provider
        user.uid = auth.uid
        user.name = auth.info.name
        user.oauth_token = auth.credentials.token
        user.refresh_token = auth.credentials.refresh_token

        user.profile.first_name = auth.info.first_name
        user.profile.last_name  = auth.info.last_name 
        user.profile.email      = auth.info.email
        user.profile.location   = auth.info.location
        user.profile.phone      = auth.info.phone
        user.save!
      end
end

Upvotes: 2

Amit Sharma
Amit Sharma

Reputation: 3477

You can add validation to User model. Check following example.

class User < ActiveRecord::Base
  has_one :profile
  delegate :first_name, :last_name, :email, :phone, :location, to: :profile

  validate :profile_exists

  private

  def profile_exists
    self.errors.add("profile", "already exists.") if self.profile.present?
  end
end

Some edit for your code, check following.

def self.from_omniauth(auth)
  where(auth.slice(:provider, :uid).permit!).first_or_initialize.tap do |user|
    user.provider = auth.provider
    user.uid = auth.uid
    user.name = auth.info.name
    user.oauth_token = auth.credentials.token
    user.refresh_token = auth.credentials.refresh_token
    user.auth_token = auth.credentials.token
    user.instance_url = auth.credentials.instance_url
    user.save!
    if user.profile.present?
      user.profile.update(email: auth.info.email)
    else    
      profile = user.build_profile(first_name: auth.info.first_name, last_name: auth.info.last_name, email: auth.info.email, location: auth.info.location, phone: auth.info.phone)
      profile.save
    end   
  end
end

Upvotes: 0

Related Questions