Skip to main content

Saving _form along with has_many through items

General • Asked by Michael Stitt

Hi Chris,

I'm having difficulty wrapping my head around how to save a form (Kit) that includes optional items for a has_many through relationship (AmazonProductKit). Here are my models:

class Kit < ActiveRecord::Base
  has_many :amazon_product_kits
  has_many :amazon_products, through: :amazon_product_kits
end

class AmazonProduct < ActiveRecord::Base
  has_many :amazon_product_kits
  has_many :kits, through: :amazon_product_kits
end

class AmazonProductKit < ActiveRecord::Base
  belongs_to :kit
  belongs_to :amazon_product

  validates :quantity, presence: true
end

What I'd like to do with the Kits#_form is capture a couple Kit attributes (title, persons, and description) and then also allow the user to pick any AmazonProduct objects they'd like included in that Kit (this is how the form functions now, however, when I save it there are no AmazonProductKit objects being stored). I'd also like to have the ability to capture the quantity for each checked AmazonProductKit in a dropdown menu, but I haven't figured out how go about doing that.

So, I know I need to modify my controller and _form, I'm just not sure what exactly. Here's my kits_controller.rb:

class KitsController < ApplicationController
  before_action :set_kit, only: [:show]

  def index
    @kits = Kit.all
  end

  def show
  end

  def new
    @kit = Kit.new
  end

  def create
    @kit = Kit.create(kit_params)

    if @kit.save
      flash[:success] = "Kit has been created."
      redirect_to kit_path(@kit)
    else
      flash[:alert] = "Kit has not been created."
      render "new"
    end
  end

  private

    def set_kit
      @kit = Kit.find(params[:id])
    end

    def kit_params
      params.require(:kit).permit(:title, :persons, :description, :amazon_product_kits => [])
    end
end

And here's my kit _form.html.erb:

<%= form_for(@kit) do |f| %>
  <% if @kit.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@kit.errors.count, "error") %> prohibited this kit from being saved:</h2>

      <ul>
      <% @kit.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>


  <div class="field form-group">
    <%= f.label :title %><br>
    <%= f.text_field :title, required: true, autofocus: true, placeholder: "e.g. 72-hour Emergency Kit", class: "form-control" %>
  </div>
  <div class="field form-group">
    <%= f.label :persons %><br>
    <%= f.text_field :persons, autofocus: true, placeholder: "e.g. 1", class: "form-control" %>
  </div>
  <div class="field form-group">
    <%= f.label :description %><br>
    <%= f.text_area :description, rows: 10, autofocus: true, placeholder: "e.g. http://www.monkeysee.com/play/28716-orlando-s-newest-tourist-destination", class: "form-control" %>
  </div>

  <div class="field form-group">
    <%= collection_check_boxes(:kit, :amazon_product_kit_ids, AmazonProduct.all, :id, :title) do |b| %>
      <%= b.check_box %>
      <%= b.label %>
      <br>
      <!-- capture `quantity` of this AmazonProduct if checked -->
    <% end %>
  </div>


  <div class="actions form-group">
    <%= f.submit "Save Kit", class: "submit-button btn btn-default" %>
  </div>

<% end %>

Let me know if you think I should alter how I've constructed my model relationships or if I should consider tweaking how a new Kit is captured. Thanks in advance!


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.