Rails 6 Adding Join Model Records with Nested Attributes

Viewed 90

I have three models related in a has many through: PizzaItem, PizzaItemTopping, and Topping, and I'm trying to build a form where it will create records for PizzaItemTopping for only the topping options the user has selected.

Typically I would do something like this for selecting nested fields:

<%= form_with(model: @pizza_item) do |f| %>
  # my form fields

  <%= f.collection_check_boxes :topping_ids, @toppings, :id, :name %>
<% end %>

This works fine and adds only the selected toppings, but I have a 'quantity' field in my PizzaItemTopping model which I want the user to be able to customize. So I tried this:

 <% @toppings.each do |topping| %>
   <%= form.fields_for :pizza_item_toppings do |f| %>
     <%= f.number_field :quantity, value: 0, id: nil %>
     <%= f.hidden_field :topping_id, value: topping.id, id: nil %>
   <% end %>
 <% end %>

But this will create a PizzaItemTopping record for every topping that exists which is not ideal. Is there a way for it to create only the records the user has selected, or the records that have a quantity of 0?

This is the workaround I currently have, but I'm looking for advice on a better approach.

 # pizza_items_controller.rb
 @pizza_item = @order.pizza_items.new(pizza_item_params)

# Do not save toppings if their quantities are 0
@pizza_item.pizza_item_toppings.each do |x| 
  @pizza_item.pizza_item_toppings.delete(x) if x.quantity == 0 
end

  
1 Answers
class PizzaItem < ApplicationRecord
  # ...
  accepts_nested_attribute_for :pizza_item_toppings, 
    reject_if: ->{ |attributes| attributes['quantity'] == 0 }
end

Use the reject_if: option to silently ignore any new record hashes if they fail to pass your criteria.

See Active Record Nested Attributes.

Related