I’m using the Devise gem and I wanted to only require the “Current Password” field for account updates when the password was being changed. For other changes, I didn’t want to require the field. This requirement was also important for me because some of my Users sign-up using Facebook. In these cases, they might not have a password and would not be able to make any account changes.
I found my answer in this SO question and this Devise article.
First, you need a Registrations controller for your resource (in my case, the resource being used with Devise is my User model), if you don’t have one already:
in controllers:
- Create users/registrations_controller.rb
Users::RegistrationsController < Devise::RegistrationsController def update self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key) if resource.update_with_password(params[resource_name]) set_flash_message :notice, :updated if is_navigational_format? sign_in resource_name, resource, :bypass => true respond_with resource, :location => after_update_path_for(resource) else clean_up_passwords(resource) respond_with_navigational(resource){ render_with_scope :edit } end end
- Add this to routes.rb
devise_for :users, controllers: {registrations: 'registrations'}
Next, add new methods to your model (user.rb in my case):
#to remove the current password check if updating a profile originally gotten via oauth (fb, twitter)
def update_with_password(params={})
if params[:password].blank?
params.delete(:current_password)
self.update_without_password(params)
else
self.verify_password_and_update(params)
end
end
def update_without_password(params={})
params.delete(:password)
params.delete(:password_confirmation)
result = update_attributes(params)
clean_up_passwords
result
end
def verify_password_and_update(params)
#devises' update_with_password
# https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb
current_password = params.delete(:current_password)
if params[:password].blank?
params.delete(:password)
params.delete(:password_confirmation) if params[:password_confirmation].blank?
end
result = if valid_password?(current_password)
update_attributes(params)
else
self.attributes = params
self.valid?
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false
end
clean_up_passwords
result
end