ruby on rails - Devise with Models User and Profile + Omniauth Facebook -
our app uses devise registration , works perfect user model , profile model.
save registration infos form users table , create profile in profiles table on sql infos , nested user_id.
the omniauth facebook working save things user model, want save name, username fetched facebook auth profile model devise registration do.
table users
| id | email | encrypted_password | reset_password_token | reset_password_sent_at | remember_created_at | sign_in_count | current_sign_in_at | last_sign_in_at | current_sign_in_ip | last_sign_in_ip | created_at | updated_at | role_id | provider | uid |
table profiles
| id | user_id | username | name | lastname | gender | birthday | created_at | updated_at |
model user.rb
class user < activerecord::base has_one :profile, :dependent => :destroy, autosave: true accepts_nested_attributes_for :profile # include default devise modules. others available are: # :confirmable, :lockable, :timeoutable , :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:facebook] belongs_to :role before_create :set_default_role def self.find_for_facebook_oauth(auth) where(auth.slice(:provider, :uid)).first_or_create |user| user.provider = auth.provider user.uid = auth.uid user.email = auth.info.email user.password = devise.friendly_token[0,20] end end def self.new_with_session(params, session) super.tap |user| if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] user.email = data["email"] if user.email.blank? end end end private def set_default_role self.role ||= role.find_by_name('registered') end end
model profile.rb
class profile < activerecord::base belongs_to :user validates :username, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false }, format: { with: /\a[a-za-z0-9]*\z/, message: "deve contar apenas letras e nĂºmeros" } validates :name, presence: true, length: {maximum: 255} validates :lastname, presence: true, length: {maximum: 255} validates :gender, presence: true, inclusion: %w(m f) validates :birthday, presence: true end
controller application_controller.rb (to handle permits of custom fields)
class applicationcontroller < actioncontroller::base # prevent csrf attacks raising exception. # apis, may want use :null_session instead. protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, :password_confirmation, :provider, :uid, profile_attributes: [:name, :lastname, :username, :birthday, :gender, :id]) } devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email, :password, :remember_me, :provider, :uid) } devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password) } end end
anyone knows how can make omniauth facebook runs devise registration create profile user, integration 2 models user , profile without break devise registration :p ?
thank :)
i don't know facebook sign or sign in flow of app i'm going assume when user clicks on sign in or sign facebook, app fetches email facebook , create new user if email not present in db else sign them in.
to achieve need override find_for_facebook_oauth(auth)
method. can in method
def self.find_for_facebook_oauth(auth) if user = user.find_by_email(auth.info.email) # search db user email coming fb return user #returns user can sign him/her in else user = user.create(provider: auth.provider, # create new user if user same email not present uid: auth.uid, email: auth.info.email, password: devise.friendly_token[0,20]) user.create_profile(name: auth.info.name, # need check how access these attributes auth hash using debugger or pry #your other profile attributes ) return user end end
and callback method same
class users::omniauthcallbackscontroller < devise::omniauthcallbackscontroller def facebook # need implement method below in model (e.g. app/models/user.rb) @user = user.find_for_facebook_oauth(request.env["omniauth.auth"]) if @user.persisted? sign_in_and_redirect @user, :event => :authentication #make sure user confirmed else it'll throw error set_flash_message(:notice, :success, :kind => "facebook") if is_navigational_format? else session["devise.facebook_data"] = request.env["omniauth.auth"] redirect_to new_user_registration_url end end end
if flow yahoo render form autofilled fields using data coming facebook instead of creating can initialise user
, profile
inside find_for_facebook_oauth(auth)
method statements
user = user.new(#user attributes) user.build_profile(#profile attributes) return user # , return initialised user
since user not in db execute else block in facebook callback method , render sign in page fields autofilled.
Comments
Post a Comment