Search code examples
ruby-on-railsformsformtasticjoin

Join Table Quantity


I'm learning Rails building an ordering system and I'm stuck trying to build a form for Orders. My models look like this:

class Restaurant < ActiveRecord::Base
    has_many :orders
end

class Order < ActiveRecord::Base
    belongs_to :restaurant
    has_many :order_recipes, dependent: :destroy
    has_many :recipes, through: :order_recipes
end

class Recipe < ActiveRecord::Base
    belongs_to :restaurant
    has_many :order_recipes
    has_many :orders, through: :order_recipes
end

I used to handle the input for Recipes using checkboxes, which only allowed me to add one of each recipe:

<%= form_for([@restaurant, @order]) do |f| %>
        <%= f.label :Table_Number %>
        <%= f.number_field :table_id %>

        <strong>Recipes: </strong>
        <br>
        <%= f.collection_check_boxes :recipe_ids, @recipes, :id, :name do |cb| %>
            <% cb.label(class: "checkbox-inline input_checkbox") {cb.check_box(class: "checkbox") + cb.text} %>
        <% end %>
        <%= f.collection_select(:recipe_ids, @recipes, :id, :name) %>
        <%= f.submit(@order.new_record? ? "Create Order" : "Edit Order", class: "btn btn-success") %>
<% end %>

But now I need to also handle quantities. So I added the "quantity" column to the order_recipes table. And I can't figure out how to build the proper form to be able to submit an Order object, with an order_recipe array of objects containing [recipe_id, order_id, quantity] per row. I'm also opened to using formtastic if it makes things easier, although I'm not very good with it yet.


Solution

  • ETA: Since the quantity field is on the orders_recipes table, you'll want to create an @orders_recipes object with all the correct recipe_ids instead:

    @orders_recipes = @recipes.map{|r| @order.order_recipes.build(recipe: r)}
    

    Then you can use the FormHelper's fields_for method:

    <%= f.fields_for :order_recipes, @order_recipes do |orf| %>
      <%= orf.hidden_field :recipe_id %>
      Quantity: <%= orf.number_field :quantity %>
    <%- end -%>
    

    If desired, you'll need to "manually" remove order_recipes with nil or 0 values for quantity.

    For this to work, you need an accepts_nested_attributes_for in your model, like so:

    class Order < ActiveRecord::Base
      …
      accepts_nested_attributes_for :order_recipes
    end