I have a model Food that has many food_varients. The FoodVarient is a model that will be set by the admin of the system. For Example the food varients could be Hot,Spicy,Extra Cheese, etc. And a food can have these varients.
Since, Food has_many food_varients, I decided to use nested form to allow the admin to create a new food item and also select food_varients that the food might have from the pre-defined food_varients created before-hand by the admin.
This is what my FoodsController
looks like:
class FoodsController < DashboardBaseController
# GET /foods/new
def new
@food = current_department.foods.new
@food.food_varients.build
end
# GET /foods/1/edit
def edit
end
def food_params
params.require(:food).permit(:name, :description,food_varients_attributes[:id,:varient_id])
end
end
I have also accepted the nested attribute in my Food.rb
file as follows:
class Food < ApplicationRecord
has_many :food_varients, dependent: :destroy
has_many :varients, through: :food_varients, dependent: :destroy
accepts_nested_attributes_for :food_varients, reject_if: proc { |attributes| attributes['varient_id'] == "0" }
And this is what my form looks like, to add food:
= form_for @food do |f|
.field.form-group
= f.label :name
= f.text_field :name, class: 'form-control', tabindex: 1
.field.form-group
= f.label :description
= f.text_area :description, class: 'form-control', tabindex: 3
........
//**Nested Form Starts from here**
- current_department.varients.each do |varient|
= f.fields_for :food_varients do |g|
= g.label :varient_id, varient.title
= g.check_box :varient_id,{} ,varient.id
I created the nested form by looping around each instance of the Varient model, that was created by the admin, and giving the admin the options to add the food_varients as the new food item is being created.
Problem:
The create is working fine, and the nested attributes are being saved as expected. But, when i try to edit the food item, the nested form is showing duplicate fields. For Example: If originally the food was set to have varients (sweet, and sour). Now, the edit page of the food item is showing me 4 fields instead of the two, with two checked sweet and sour fields, and two unchecked. sweet and sour fields.
Is there a different approach that i must be trying? Because ever other example that i see, makes the use of text_fields to save the nested attribute dynamically, while I am looping through the already existing varient instance.
You don't need to use nested attributes at all here. Just use the collection helpers along with the varient_ids=
setter:
= form_for @food do |f|
.field.form-group
= f.label :name
= f.text_field :name, class: 'form-control', tabindex: 1
.field.form-group
= f.label :description
= f.text_area :description, class: 'form-control', tabindex: 3
.field.form-group
= f.label :varient_ids
= f.collection_select :varient_ids, Varient.all, :id, :name
class FoodsController < DashboardBaseController
# GET /foods/new
def new
@food = current_department.foods.new
end
# ...
def food_params
params.require(:food).permit(:name, :description, varient_ids: [])
end
end
Rails will automatically add/destroy rows on the join table. The correct spelling is also Variant:
variant (plural variants)
Something that is slightly different from a type or norm.
- https://en.wiktionary.org/wiki/variant#English