Ask A Question

Notifications

You’re not receiving notifications from this thread.

Rails for Beginners Part 19: Edit Password Discussion

Editing the password with an empty string (i.e. not filling the fields and clicking right away on the submit button) doesn't throw any error, Current.user.update(password_params) returns true and the redirection is working. However, the password is not changed in the database. I don't get how it is possible that the update method returns true but at the same time, the database is not updated and there is not even a error message in the logs.

Reply

maybe you should authenticate the form using html and javascript or doing something like this
https://guides.rubyonrails.org/active_record_validations.html

I tried but not worked here for me, so, I should use some regex in html and javascript, but I think rails has a better way.

Reply

Yes, you can simply add this in your user model: "validates :password, presence: true". Thus, it's attaching an error "Password can't be blank" to your model's instance which is displayed on the edit view. What I don't understand is that, when you don't add this validation and submit an empty form, you do get redirected to the rootpah with the notice "password updated!", which means Current.user.update(password_params) is working. So I would expect the password to be changed to an empty string, but it is not the case. The password remains unchanged. I hope it makes sense, sorry, english is not my native language.

Reply

Ok, so answering to myself: this is a default implementation (discussed here: https://github.com/rails/rails/issues/34348). And the reason for this implementation is, I quote: "the reason the password is ignored for empty strings is that if a user has a form with multiple fields (including password) and they update details but don't enter the password, then we want to allow the other details to be updated without the password being effected.". Makes sense eventually :)

Reply

Nice catch! That was really interesting to learn & try.

Reply

I had the exact same question. Thanks for this thread and answers!

Reply

For that, I just added validates to my user model, like that:

class User < ApplicationRecord
  has_secure_password

  validates :email, presence: true, format: {
    with: URI::MailTo::EMAIL_REGEXP,
    message: 'invalid email address provided'
  }

  validates :password, presence: true
end
Reply

As Alex says, this is a common way to add some validation (to password in this case), you can even add something like:
validates :password, presence: true, length: {minimum: 6, maximum: 30}
in order to add length validation too, getting responses like "Password is too short (minimum is 6 characters)" when the entered password does not meet this validation.
On the other hand, many user profile forms show password and password confirmation fields, if the user doesn't enter any value on these, the password remains the same, but if other fields have changed, these can be updated on the same action.

Reply

I'm having an issue where it does not validate the confirmation to the new password. So no matter if the two are different, it simply updates the password with whatever is in the password field.

Reply

Scratch that... no issue. My poor spelling was the problem. Only took 45 minutes to figure that out. :/

Reply

By the way, what's the reason that you've created a bang method called require_user_signed_in!. I know the general idea behind bang methods but how does that apply here? Why not just require_user_signed_in?

Reply

I did not notice ! at the end of method name. Wondering if that was intentional..

Reply

It's okay to put the if conditional at the end of the require_user_logged_in! method? Huh…

Reply

Yes, it's a common "rails way" to write an if statement in a single line when possible

Reply

I was getting the error: Error: Form responses must redirect to another location in my dev tools (and the change password button was also not throwing any flash messages). I had to add status: :unprocessable_entity to my passwords_controller.rb file. Full code:

class PasswordsController < ApplicationController 
    before_action :require_user_logged_in!

    def edit
    end

    def update
        if Current.user.update(password_params)
           redirect_to root_url, notice: 'パスワードを変更しました'
       else
           render :edit, status: :unprocessable_entity
       end
    end

    private

    def password_params
        params.require(:user).permit(:password, :password_confirmation)
    end
end 
Reply

Hi, I had to add the status too, Rails v7 in my case requires this part.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 86,946+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.