I'm using devise, omniauth and client-side-validation like described in ryan bates railscasts.
I'm now facing a problem with the password validation which should be omitted when registering via omniauth 3rd party provider.
Registration form (html.erb):
Sign up
Register via 3rd party networks
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :validate => true) do |f| %>Register directly
<%= f.label :firstname %> <%= f.text_field :firstname %>
<%= f.label :lastname %> <%= f.text_field :lastname %>
<%= f.label :email %> <%= f.text_field :email %>
<%= f.label :password %> <%= f.password_field :password %>
<%= f.label :password_confirmation %> <%= f.password_field :password_confirmation %>
<%= f.submit "Register now", :class => "button-big" %>
<% end %>
My user model has a - see UPDATE below
validates :password, :presence => true, :confirmation =>true
clause and the password_required? definition
def password_required?
(authentications.empty? || !password.blank?)
end
When I'm registering via omniauth 3rd party provider the registration form correctly pops up and the user is asked to enter an email address. Unfortunately the user has to enter a password although he shouldn't be prompted due to registration via 3rd party.
Can anybody give me a hint, how to accomplish?
Thanks and best regards
Jan
UPDATE: to give a more specific view I added some more code snippets
AuthenticationsController:
class AuthenticationsController < ApplicationController
def index
@authentications = current_user.authentications if current_user
end
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create(:provider => omniauth['provider'], :uid => omniauth['uid'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth.except('extra')
redirect_to new_user_registration_url
end
end
end
def destroy
@authentication = current_user.authentications.find(params[:id])
@authentication.destroy
flash[:notice] = "Successfully destroyed authentication."
redirect_to authentications_url
end
end
RegistrationsController: class RegistrationsController < Devise::RegistrationsController
def create
super
session[:omniauth] = nil unless @user.new_record?
end
private
def build_resource(*args)
super
if session[:omniauth]
@user.apply_omniauth(session[:omniauth])
@user.valid?
end
end
end
User Model: class User < ActiveRecord::Base # associations has_many :authentications
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:validatable, :email_regexp => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
# Setup accessible (or protected) attributes for your model
attr_accessible :firstname, :lastname, :email, :password, :password_confirmation, :remember_me
# validations
validates :firstname, :presence => true
validates :lastname, :presence => true
validates :email, :presence => true, :uniqueness => true
validates_email :email
validates :password, :presence => true, :confirmation =>true
# omniauth reference 3rd party
def apply_omniauth(omniauth)
if self.firstname.blank?
self.firstname = omniauth['info']['first_name'].presence || omniauth['info']['name'].presence || " "
end
if self.lastname.blank?
self.lastname = omniauth['info']['last_name'].presence || omniauth['info']['name'].presence || " "
end
if self.email.blank?
self.email = omniauth['info']['email'].presence
end
authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
end
# omit validation for omniauth session
def password_required?
(authentications.empty? || !password.blank?) && super
end
end
Authentication Model class Authentication < ActiveRecord::Base # associations belongs_to :user
# Setup accessible (or protected) attributes for your model
attr_accessible :user_id, :provider, :uid
end
While debugging I found out that the 'authentications.build()' in the 'apply_omniauth(omniauth)' method produces an empty object, so that the 'password_required?' is always be true and a password must be provided.
ADDITIONAL QUESTION: why does 'authentications.empty?' always return 'false'?
Thanks in advance
Jan