I have a Restaurant
model that has many DishCategory
's and also has many Dish
's through DishCategory
's. So for instance, the category Dinner would be a number of dishes associated with it. To help build the form I'm using the cocoon gem.
I'm familiar with setting up the view code for a traditional nested forms for but now that I'm going one level deeper I'm not sure how to write and where to put the inputs for dishes. Do I setup another simple_fields_for
block for dishes
inside my partial? Following the docs this is how things are currently setup:
Models
class Restaurant < ActiveRecord::Base
has_many :dish_categories, dependent: :destroy
has_many :dishes, through: :dish_categories, dependent: :destroy
accepts_nested_attributes_for :dish_categories, :reject_if => :all_blank, :allow_destroy => true
end
class DishCategory < ActiveRecord::Base
belongs_to :restaurant
has_many :dishes, dependent: :destroy
accepts_nested_attributes_for :dishes, :reject_if => :all_blank, :allow_destroy => true
end
class Dish < ActiveRecord::Base
belongs_to :dish_category
end
Restaurant Form
<%= simple_form_for(@restaurant) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
</div>
<div class="form-inputs dish-category-inputs">
<%= f.simple_fields_for :dish_categories do |f| %>
<%= render 'dish_category_fields', f: f %>
<% end %>
</div>
<div class='add-dish-category'>
<%= link_to_add_association 'Add a Dish Category', f, :dish_categories %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Dish Category Fields
<div class="dish-category-form nested-fields">
<%= f.input :name %>
<%= link_to_remove_association "Remove Category", f %>
</div>
So it looks like I did need to create an additional partial. From what I understand, the third parameter in the links_to_add_association
expects a partial associated with the model for the form you wish to nest.
Dish Category Fields
<div class="dish-category-form nested-fields">
<%= f.input :name %>
<%= link_to_remove_association "Remove Category", f %>
</div>
<div class="form-inputs dish-category-inputs">
<%= f.simple_fields_for :dishes do |f| %>
<%= render "dish_fields", f: f %>
<% end %>
</div>
<div class='add-dish'>
<%= link_to_add_association "Add Dish", f, :dishes %>
</div>
Dish Fields
<div class="dish-category-form nested-fields">
<%= f.input :name %>
<%= link_to_remove_association "Remove Dish", f %>
</div>
NOTE:
When it comes to the restaurants controller code it may trip people up in regards to whitelisting your params. Its important that you place dishes_attributes
within dish_categories_attributes
in order for everything to save properly:
Restaurants Controller
class RestaurantsController < ApplicationController
...
private
def restaurant_params
params.require(:restaurant).permit(:name, dish_categories_attributes: [:id, :restaurant_id, :name, :_destroy, dishes_attributes: [:id, :dish_category_id, :name, :description, :_destroy]])
end
end