Update join table using list of checkboxes in Rails I have Gig and Singer Active Record models (standard--no customization just yet) with a many-to-many relationship through a generic join table which holds nothing but the respective ids of Gig and Singer.  My form sends a given gig id and all the singers who will be attending, denoted with check boxes.  I need to have the ability to check or uncheck singers.  The following code works, but it does so by removing all the singers from a gig and re-adding them.  This feels hacky... is there a better way?  (I think this is all the code necessary but let me know if you need me to add anything)

class GigSingersController &lt; ApplicationController

    def create
        gig = Gig.find(params[:gig_id])
        singer_ids = params[:singer_ids] # [1, 4, 5,]
        gig.singers = []
        singer_ids.each do |id|
            singer = Singer.find(id)
            gig.singers &lt;&lt; singer
        end
        redirect_to gigs_path
    end
end


EDIT:  

As requested in the comments, here are the schema and relevant models, although as I said, they are completely generic.  Perhaps I didn't do a good job of making my question clear:  Is the best way to create these relationships when using a checkbox to remove all existing ones and recreate them from the boxes currently checked, thereby removing any that the user unchecked on an edit?

ActiveRecord::Schema.define(version: 2019_07_19_195106) do

  create_table "gig_singers", force: :cascade do |t|
    t.integer "gig_id"
    t.integer "singer_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "gigs", force: :cascade do |t|
    t.string "name"
    t.text "notes"
    t.datetime "datetime"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "singers", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.boolean "active"
  end

class Gig &lt; ApplicationRecord
    has_many :gig_singers
    has_many :singers, through: :gig_singers
end

class GigSinger &lt; ApplicationRecord
    belongs_to :gig
    belongs_to :singer
end

class Singer &lt; ApplicationRecord
    has_many :gig_singers
    has_many :gigs, through: :gig_singers

end
Actually, Active Record can work with joined collection (including has_many :through) from the box.

So, you just need to pass new collection instead of old, and AR will delete excessive and add new records.

In your code, need to change create method body to:

gig = Gig.find(params[:gig_id])
singer_ids = params[:singer_ids] # [1, 4, 5,]
gig.singers = Singer.find(singer_ids)
redirect_to gigs_path