Devise: change password

ralphos picture ralphos · Feb 22, 2012 · Viewed 9.2k times · Source

I've been stuck on this for over 24hrs trying to follow other solutions posted here, but I can't get this to work. I'm new to Rails and need help!

I want to get my /users/edit page working so that I can simply change a users password. Originally, I wanted to do it without current_password but I don't mind leaving it in there as long as I can get the password changing and updating.

Here's what I did:

I followed the example in the Devise Wiki and inserted it into my Users controller which I specified to inherit from Devise::RegistrationsController

class UsersController < Devise::RegistrationsController
  ...
end

I changed my routes:

devise_for :users, :controllers => { :registrations => 'users' } do 
  match '/users' => 'users#index'
end

And here's my model:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  attr_accessor :password, :password_confirmation, :current_password
  attr_accessible :email, :password, :password_confirmation, :current_password,      :remember_me, :full_name, :coach, :bio 

  validates :full_name, presence: true

end

I was assuming the UsersController I created would override the Registrations controller and that I would be able to change/update password. It works to the extent the redirect to root_path happens (which is only meant to happen after updating without current password) but the new password is not saved (I checked the logs and there was no SQL to show it was saved)...

Any ideas?

Answer

fiestacasey picture fiestacasey · Feb 22, 2012

Try doing something similar to: Devise Forgot Password for logged in user

This lets you have a separate view for changing the password.

The key is that I couldn't ever get it working in devise, so I wrote my own solution in the users controller and post to that instead of using the methods provided by devise.

add this to your user form where you want to be able to edit the password:

<%= form_for(@user, :url => url_for(:action => :do_reset_password) , :html => { :method => :post }) do |f| %>

  <%= f.hidden_field :reset_password_token %>

  <div><%= f.label :password, "New password" %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation, "Confirm new password" %><br />
  <%= f.password_field :password_confirmation %></div>

  <div><%= f.submit "Change my password" %></div>
<% end %>

users controller:

    def do_reset_password
        id = params[:id]

        # there may be a better way of doing this, devise should be able to give us these messages
        if params[:user][:password] != params[:user][:password_confirmation]
            flash[:alert] = "Passwords must match." 
              redirect_to :back
              return
        end
        if @user.reset_password!(params[:user][:password],params[:user][:password_confirmation])
            @user.save
            respond_to do |format|
                format.html { redirect_to '/home', notice: 'Your password has been changed.' }
            end
        else
            flash[:alert] = "Invalid password, must be at least 6 charactors." 
              redirect_to :back 
        end
    end

config/routes.rb

resource :users do
  post 'do_reset_password'
end