Search code examples
ruby-on-railssimple-form

Simple Form check box for join table relationship


I can't figure this out for the life of me but here are my models:

class User < ApplicationRecord
  has_many :user_stores
  has_many :stores, through: :user_stores        
end

class UserStore < ApplicationRecord
  belongs_to :user
  belongs_to :store
end

class Store < ApplicationRecord
  has_many :user_stores
  has_many :users, through: :user_stores
end

So I have a join table, I'm trying to make a form, which would have selected checkboxes next to the store names that the user has selected (this information would come from the join table relationship) and open checkboxes for the remaining stores (coming from the Store model). How do I show that in the view/make it work in the controller as well. Would I use collections instead? ( I am using Devise and Simple Form gem )

This is what I have so far:

<h1>Add Favorite Stores</h1>
<%= simple_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
  <%= f.fields_for :stores, @user.stores do |s| %>
    # not sure if this is the right way or not
  <% end %>
  <%= f.button :submit %>
<% end %>

Store Controller:

class StoresController < ApplicationController
...
  def new
    @user = current_user
    @stores = Store.all
    # @user.stores => shows user's stores (from join table)
  end
end

Solution

  • When you set up a one or many to many relationship in rails the model gets a _ids setter:

    User.find(1).store_ids = [1,2,3]
    

    This would for example setup a relation between user 1 and the stores with ids 1,2 and 3.

    The built in Rails collection form helpers make use of this:

    <%= form_for(@user) do |f| %>
      <% f.collection_check_boxes(:store_ids, Store.all, :id, :name) %>
    <% end %>
    

    This creates a list of checkboxes for each store - if an association exists it will already be checked. Note that we are not using fields_for since it is not a nested input.

    SimpleForm has association helpers which add even more sugar.

    <h1>Add Favorite Stores</h1>
    <%= simple_form_for(@user, html: { class: 'form-horizontal' }) do |f| %>
      <%= f.association :stores, as: :check_boxes %>
      <%= f.button :submit %>
    <% end %>