Editing/Updating user not working when using has_secure_password in Rails 4
ruby-on-rails-4
Solution
Since this is an `update` action instead of a `create` the validations might not be running.
From ActiveModel::SecurePassword:
Validations for presence of password on create, confirmation of password (using a password_confirmation attribute) are automatically added.
Relevant section of code from secure_password.rb
def has_secure_password(options = {})
...
if options.fetch(:validations, true)
validates_confirmation_of :password, if: lambda { |m| m.password.present? }
validates_presence_of :password, :on => :create
validates_presence_of :password_confirmation, if: lambda { |m| m.password.present? }
end
...
end
Problem
I am using Michael Hartl's Ruby on Rails tutorial to make my own user auth system. Everything is working fine when creating a new user. When trying to update a user is when things are no longer making sense. I am using the `has_secure_password` method. So I let it worry about taking the password and encrypting it. But when I update, some weird behavior occurs. The important part is that I can update a user without entering any password and its confirmation. But if I enter a password and no confirmation, it requires a confirmation. If I only enter a confirmation password, that updates with no error. Now since `has_secure_paassword` is suppose to be doing that part, why is it not doing it when updating? One thing I did not add in my User model is a presence validation due to this line in the tutorial: Presence validations for the password and its confirmation are automatically added by has_secure_password. I am aware that there are similar questions on this, but none seem to enforce strong parameters, which is my guess as to why it is not working for me. Some of my code below. User Controller ``` def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) # if params[:user][:password].blank? # render 'edit' # return # end if @user.update(user_params) redirect_to @user, notice: 'User successfully updated' else render 'edit', notice: 'Failed to update profile.' end end def user_params params.require(:user).permit( :username, :email, :phone, :bio, :password, :password_confirmation ) end ``` User model ``` class User < ActiveRecord::Base before_save {self.email = email.downcase} has_secure_password before_create :create_remember_token validates :username, presence: true, length: {maximum: 255, minimum: 5}, format: { with: /\A[a-zA-Z0-9]*\z/, message: "may only contain letters and numbers." }, uniqueness: true VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } #... Other User stuff. ``` Edit form ``` <div class="col-xs-8 col-xs-offset-2"> <%= form_for(@user, :html => {:class => 'well'}) do |f| %> <div class="form-group"> <%= f.label :username %><br /> <%= f.text_field :username, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :phone %><br /> <%= f.phone_field :phone, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :bio %><br /> <%= f.text_area :bio, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :email %><br /> <%= f.email_field :email, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :password %><br /> <%= f.password_field :password, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation, class: 'form-control' %> </div> <div class="form-group"> <%= f.submit "Update", class: 'btn btn-default' %> </div> <% end %> </div> ```