29

I am using ActiveAdmin as my administration backend in my rails app. Basically, I have an admin_user and a user model.

When I create a new user from an admin account, I specify an email and a password, that is ok.

Let's say I then want to modify the user's email but not the password... it seems this cannot be done as the password field cannot be blank when updating a user.

Is there a configuration somewhere that would consider that the password is unchanged is the fields (password and password_confirmation) are left blank while updating a user?

rlandster
  • 7,294
  • 14
  • 58
  • 96
Luc
  • 16,604
  • 34
  • 121
  • 183

5 Answers5

98

You don't really need to mess at all with Devise's registration controller, you can just ignore empty password fields inside ActiveAdmin's resource controller:

ActiveAdmin.register User do
  controller do

    def update
      model = :user

      if params[model][:password].blank?
        %w(password password_confirmation).each { |p| params[model].delete(p) }
      end

      super
    end
  end
end
Troy
  • 5,319
  • 1
  • 35
  • 41
mauriciomdea
  • 2,954
  • 3
  • 15
  • 10
22

Devise provides an update_without_password method that you can use when updating a user if no password is entered. Using that method, you can customize the update method in your ActiveAdmin users controller.

 def update
   @user = User.find(params[:id])
   if params[:user][:password].blank?
     @user.update_without_password(params[:user])
   else
     @user.update_attributes(params[:user])
   end
   if @user.errors.blank?
     redirect_to admin_users_path, :notice => "User updated successfully."
   else
     render :edit
   end
 end

The Devise Wiki has more information about this method if your interested.

rocket scientist
  • 2,427
  • 1
  • 19
  • 28
10

You need to evaluate password and password_confirmation in the if statement, to apply the validations on "password_confirmation", eg for my case:

#app/admin/user.rb
controller do
  def update
    if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
      params[:user].delete("password")
      params[:user].delete("password_confirmation")
    end
    super
  end
end


#app/model/user.rb
validates :name, :email, presence: true
validates :password, :password_confirmation, presence: true, on: :create
validates :password, confirmation: true

This allows me to validate password presence only when I create a new user and update without changing his password.

This work for me, I hope this is helpful.

I hope this is helpful.

calrrox
  • 329
  • 4
  • 8
1

You can validate the password only on create because bcrypt when updating will still validate password presence.

class User
   validate :password, :password_confirmation, presence: true, on: :create 
end

In my opinion this is much simpler while causing no risk, and allows you to use a single partial form for create and update routes with an if statement showing/not showing password input field like so:

<%= form_for(user, url: users_path) do |form| %>
<%= form.label 'Name' %><br>
<%= form.text_field :name%><br>

<%= form.label 'email' %><br>
<%= form.text_field :email%><br>

<%= form.label 'Password' %><br>
<%= form.password_field :password%><br>

**<% if form.object.new_record? %>**
    <%= form.label 'password_confirmation' %><br>
    <%= form.password_field :password_confirmation%><br>
**<% end %>**

<%= form.submit (form.object.new_record? ? 'create' : 'update')  %>
0

As told in comments on the @mauriceomdea answer, the def update is missing (or at least was missing for me, henerating an error.)

Here is a more complete version that worked for me :

You don't really need to mess at all with Devise's registration controller, you can just ignore empty password fields inside ActiveAdmin's resource controller:

ActiveAdmin.register User do

  controller do  
    def update
      model = :user

      if params[model][:password].blank?
        %w(password password_confirmation).each { |p| params[model].delete(p) }
      end

      super
    end
  end
end

hope this helps someone.

Jonathan Simonney
  • 585
  • 1
  • 11
  • 25