Ask A Question

Notifications

You’re not receiving notifications from this thread.

Use Multiple Checkboxes on a Rails Form

Brent Phillips asked in Rails

Greetings,

I have a bit of a situation that I cannot find any good resources on and its driving me nuts! I have the following setup:

Gems: Devise, Rolify

Controllers: ProfilesController, UsersController

Models: Profile, User, and user_roles(its a join table)

All that I am trying to do is create a simple form partial to add and remove roles to users. I would like to use checkboxes to accomplish this. The form needs to be placed inside of a Profiles form.

So, what is the best strategy for doing this?

Reply

Can you telll us a bit more about your database schema?

Reply

Schema

 create_table "profiles", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "f_name",                limit: 50
    t.string   "m_name",                limit: 50
    t.string   "l_name",                limit: 50
    t.string   "phone",                 limit: 12
    t.datetime "created_at",                        null: false
    t.datetime "updated_at",                        null: false
  end
create_table "roles", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "name"
    t.string   "resource_type"
    t.integer  "resource_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree
    t.index ["name"], name: "index_roles_on_name", using: :btree
end
    create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "email",                  default: "",    null: false
    t.string   "encrypted_password",     default: "",    null: false
    t.string   "reset_password_token"
    t.string   "username"
    t.integer  "status"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,     null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.boolean  "archived",               default: false
    t.integer  "failed_attempts",        default: 0,     null: false
    t.string   "unlock_token"
    t.datetime "locked_at"
    t.datetime "created_at",                             null: false
    t.datetime "updated_at",                             null: false
    t.integer  "workflow_state"
    t.integer  "organization_id"
    t.integer  "req_access_id"
    t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
    t.index ["organization_id"], name: "index_users_on_organization_id", using: :btree
    t.index ["req_access_id"], name: "index_users_on_req_access_id", using: :btree
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
    t.index ["username"], name: "index_users_on_username", unique: true, using: :btree
  end
    ```
    ```
    create_table "users_roles", id: false, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.integer "user_id"
    t.integer "role_id"
    t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree
  end
    ```
    # HTML.ERB
    ```
    <%= form_for @user do |f| %>
<%= f.collection_check_boxes(:role_ids, Role.all.order('id DESC'), :id, :name) do |b| %>
<div class="input-group mb-3">
  <div class="input-group-prepend">
    <div class="input-group-text">
      <%= b.check_box %>
    </div>
  </div>
  <%= b.label class: 'form-control text-center text-uppercase' %>
  <% end %>
</div>
<%= f.submit "Assign Role", class: 'btn btn-primary btn-block' %>

<% end %>
Reply

Your profile table is not linked to the user which seems to be weird.

What you could do is sth like:

<%= form_for @user, html: { multipart: true } do |f| %>
  <div class="form-group">
   <%= f.label :role_ids, "User roles" %>
      <%= f.collection_select :role_ids, Role.all.order(name: :asc), :id, :name, {}, { multiple: true, class: "form-control" } %>
      <div class="explanation">Choose one or more roles</div>
    </div>
      </div>
      ....
    <% end %>

Users controller

def new
      @user = User.new
      @user.user_roles.build
    end

    def create
      @user = User.new(user_params)
        if @user.save
         ........
    end

    def user_params
  params.require(:product).permit(:name, ...., role_ids: [])
end

This is kinda the Rails convention. But all you have to do basically is showing the roles on the form to choose from. So you have to query those. In the code I added it to the view. If you like it more you can puy in the controller too. Then you have to send over the role ids that are chosen in the form. Of course you have to whitelist them. Then you can just save it to the db when user is saved. Nothing fancy.

Reply

The profile is linked to the user. A user has_one profile and a profile belongs_to a user. Also, the code provided produces a multiselect box. I am looking for a multiselect with checkbox solution.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 85,376+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.