Updating Roles in rolify using ActiveAdmin

4.8k views Asked by At

Using Rails 4.0, ActiveAdmin, Rolify and CanCan, Adding and removing user roles via the activeadmin panel does not save (commit to database).

The my ActiveAdmin User and User Model look okay as I can list all the roles that apply to a user using check_boxes. Although when adding any roles or removing any roles via the checkboxes the changes do not get applied.

enter image description here

I get a notification that the user was updated successfully but as I look through the database or render the page, the roles have not been updated.

How can I get the roles to update when the form is saved?

Edit:

Using Devise also.

enter image description here

3

There are 3 answers

1
Troy On BEST ANSWER

The solution here is to allow the ActiveAdmin controller to update the role ids related to the user.

ActiveAdmin.register User do

  permit_params :email, :password, :password_confirmation, role_ids: []

Here's a form that shows a check box for each global role.

  form do |f|
    f.inputs "User Details" do
      f.input :email
      f.input :password
      f.input :password_confirmation
      f.input :roles, as: :check_boxes
    end
    f.actions
  end

While we're at it, we might as well make it possible to update the user without entering their password:

  # Allow form to be submitted without a password
  controller do
    def update
      if params[:user][:password].blank?
        params[:user].delete "password"
        params[:user].delete "password_confirmation"
      end

      super
    end
  end

Put all of this in the app/admin/user.rb.

2
MGrantley On

I just ran into this issue. The problem was with validation of presence (which I think is occurring in the database ":null => :false"). In order for the update to save, I had to fill out all fields (including password/password confirmation).

0
Yuval Karmi On

I had to add some controller code to make this work, I hope this helps:

Remember to permit the attributes you're accepting in active_admin as such (this will create the permitted_params method I'll be referring to in a bit.

Note that since we're not saving role_ids directly to the user, it doesn't even have to be a permitted param.

  permit_params :email, :password, :etc

Create a private method we could call from the create and update controllers. This method will just iterate over non-empty ids, find the associated roles, and add them to user.roles.

The create and update methods simply find call the add_roles method prior to continuing execution. ActiveAdmin makes the the existing user available through resource, but not through create. We have to find it ourselves in create!

  controller do
    def create
      @user = User.new(permitted_params[:user])
      add_roles(@user)
      create!
    end

    def update
      add_roles(resource)
      update!
    end

    private
    def add_roles(resource)
      resource.roles = []
      params[:user][:role_ids].each { |r| resource.roles.push(Role.find(r)) unless r.blank? }
    end
  end

In the activeadmin form, you can add:

  form do |f|
    # other inputs
    f.input :roles, as: :select, multiple: true, collection: Role.all
  end

And in the show page, you can display the roles as such:

  show do
    attributes_table do
      # other rows
      row :roles do |r|
        r.roles.map { |role| role.name }.join(", ")
      end
    end

Hope this helps!