Devise is currently the most used gem for authentication in Rails, and version 3.0.0 is compatible with Rails 4. For this, and for being powerful and configurable and staying out of the way (at least initially), I’ve chosen devise for my current project.

To generate a User model I left it to devise itself by issuing

$ rails generate devise MODEL
$ rake db:migrate

Al went fine, but when I wanted to be able to also do some CRUD myself on User models, I issued

$ rails generate scaffold_controller User –skip

At this point I had to fix the form helper and a couple of views, for adding email, password and password_confirmation fields. Then the controller too needed some adjustments that were a little more difficult go get properly, but the model was already fine.

The problem with the controller was changing the update action so that I’d be able to edit the email and/or the password independently.

Here is my new update

  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
    if user_params[:password].blank?
      user_params.delete(:password)
      user_params.delete(:password_confirmation)
    end

    # https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-edit-their-account-without-providing-a-password
    successfully_updated = if needs_password?(@user, user_params)
                             @user.update(user_params)
                           else
                             @user.update_without_password(user_params)
                           end

    respond_to do |format|
      if successfully_updated
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

And here is the private defs for user_params and needs_password?

  # Never trust parameters from the scary internet, only allow the white list through.
  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation)
  end

  # https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-edit-their-account-without-providing-a-password
  def needs_password?(user, params)
    params[:password].present?
  end

So the difficult part here was that you have to use the normal update method when you also want to change the password and the special update_without_password method (provided by devise) when you don’t want to change the password.

Devise also provides an update_with_password method, but that’s misleading because it requires the current_password field, only useful when you want the user herself to be able to edit her data. It should be renamed to update_with_current_password…