small medium large xlarge



Iros: Change the views/users/edit.html.erb content to

<h1>Editing user</h1>

<% form_for(@user) do |f| %>
  <%= f.error_messages %>

        <label for="user_name">Name: </label>
        <%= f.text_field :name, :size =>40 %>

        <label for="user_password">Password: </label>
        <%= f.password_field :password, :size =>40 %>

        <label for="user_password_confirmation">Confirm: </label>
        <%= f.password_field :password_confirmation, :size =>40 %>

    <%= f.submit "Update" %>
<% end %>

<%= link_to 'Show', @user %> |
<%= link_to 'Back', users_path %>


The method posted by Iros is what I first did. It’s the obvious easy solution. What I’m wondering is: how do you do this in a way that the user has to enter their current password to change their password?

I tried adding a field to edit.html.erb the way shown above but Rails always complained about it. I sort of got it to work with fields_for like this:

<% fields_for :current_password do |f| %>
<%= f.password_field :current_password %>
<% end %>

That ended up in the params has as params:current_password.

That sucks.

I decided to see if I could use User#authenticate with and that params[][] mess to see if the user’s current password was correct and then update to the new password provided. It was ugly but seemed to work okay.

Any suggestions?


To gackd. You can use password_field_tag function.

  <%= label_tag 'Current password' %>:
  <%= password_field_tag :current_password, '', :size => 40 %>

I suggest below additional code to Iros’s one.

In user.rb

class User < ActiveRecord::Base
  # ...

  validates_presence_of :name, :password

  # ...
h4. MarkG Since you already know the name of the user you’re attempting to edit, it’d be smarter to pre-populate that field…chances are that if you’re editing their account it’s because of a password change, not that they’ve legally changed their name [sure it can happen, but it’s not the most common situation :-) ]

# ...
  <label for="user_name">Name: </label>
  <%= f.text_field :name, :size =>40, :value => %>
# ...


Iros’s solution does not work for me, it changes only view layout but nothing happens on the server side. It does not update the hashed_password. Here is my solution. First, I added a new method to the user’s model:

  def self.update_user(params,salt)
    # params: {name, confirmation_password}
    user = {}
    unless params[:password_confirmation].blank?
      hashed_confirmation_password = User.encrypted_password(params[:password_confirmation],salt) 
      user[:name] = params[:name]
      user[:hashed_password] = hashed_confirmation_password
      user[:salt] = salt
    return user

and, second, I changed the update method in users_controller.rb:

  def update
    @user = User.find(params[:id])
    user = User.update_user(params[:user],@user[:salt])
    return redirect_to(:action =>:index) if user.blank?

    respond_to do |format|
      if @user.update_attributes(user)

Now, it saves an updated password if the field was changed.

But, there is always “but”, I cannot find the way how to make validation working if I add password and password_confirmation fields. If I create a new user then validation works (name,password), but if I use User.find() it does not work..


Let me explain my soution. Possibly there are more efficient ones but the Convention over configuration asks to memorize or have a lot of documentacion and/or experience. It’s not my case.

So, here is what I did:

First, I exactly made a new edit.html.erb as Iro’s one.

Second, I have modified a line and added another in the update method:

  def update
    @user = User.find(params[:id])

    respond_to do |format|
      if (@user.update_attributes(params[:user]) if !params[:user][:password].blank?) #modified line
        flash[:notice] = "User #{} was successfully updated." 
        format.html { redirect_to :action=>:index }
        format.xml  { head :ok }
        flash[:notice] = "User #{} needs a password" # added line 
        format.html { render :action => "edit" }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }

I suppose it is not the niciest code, more than that, I’m sure there is some better way to do that. But works

BTW, does anybody know why “validate :password_non_blank” in user model doesn’t work here as it did for the ‘new’ action?

Page History
  • V12: Daniel Dawson [about 2 years ago]
  • V36: Malcolm McKeown [about 2 years ago]
  • V35: Malcolm McKeown [about 2 years ago]
  • V34: Malcolm McKeown [about 2 years ago]
  • V33: Malcolm McKeown [over 2 years ago]
  • V32: Malcolm McKeown [over 2 years ago]
  • V31: Malcolm McKeown [over 2 years ago]
  • V30: Malcolm McKeown [over 2 years ago]
  • V11: Heber Massami Nunomura [almost 4 years ago]
  • V9: Andrew de Andrade [about 5 years ago]