I'm not quite sure what I'm doing wrong but when a user tries to change their password on my app, it gives an error that current_password is an unknown attribute.
Here's my code:
def configure_devise_permitted_parameters
registration_params = [:email, :password, :password_confirmation, :first_name, :last_name]
if params[:action] == 'update'
devise_parameter_sanitizer.for(:user_update) {
|u| u.permit(registration_params << :current_password)
}
elsif params[:action] == 'create'
devise_parameter_sanitizer.for(:sign_up) {
|u| u.permit(registration_params)
}
end
end
class RegistrationsController < Devise::RegistrationsController
def update
account_update_params = devise_parameter_sanitizer.sanitize(:user_update)
if account_update_params[:password].blank?
account_update_params.delete("password")
account_update_params.delete("password_confirmation")
account_update_params.delete("current_password")
end
@user = User.find(current_user.id)
if @user.update_attributes(account_update_params)
set_flash_message :notice, :updated
sign_in @user, bypass: true
redirect_to after_update_path_for(@user)
else
render "edit"
end
end
what am i doing wrong here? what should I be doing with current_password to check it is correct before saving their new password correctly?
EDIT:stack trace
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:47:in `rescue in _assign_attribute'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:42:in `_assign_attribute'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:29:in `block in assign_attributes'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:23:in `each'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:23:in `assign_attributes'
Instead of calling @user.update_attributes(account_update_params)
which blows up because current_password
isn't a field in the database (at least not in the default schema), try calling update_resource(@user, account_update_params)
which is provided by Devise::RegistrationsController which you're inheriting from. This in turn calls resource.update_with_password(params) which is provided by devise's DatabaseAuthenticatable
module and checks the current_password
before updating all the other params passed.
However, it looks like the standard DeviseController::RegistrationsController.update() would support what you want and more (e.g. handling if update needs a confirmation email); is there some reason why you need to override it?
I had the same issue today with the following version of Ruby, Rails and Devise:
Here is my solution:
app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
# Require current password if user is trying to change password.
return super if params["password"]&.present?
# Allows user to update registration information without password.
resource.update_without_password(params.except("current_password"))
end
end
app/controllers/registrations_controller.rb
.# config/routes.rb
devise_for :users, controllers: { registrations: "registrations" }
As of Devise 4,
When getting the unknown attribute for 'current_password',
no need to play with the devise_parameter_sanitizer
Go into app/controllers/registrations_controller.rb
Change
def update_resource(resource, params)
resource.update_without_password(params)
end
By
def update_resource(resource, params)
resource.update_with_password(params)
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With