This article will discuss how to create dynamic nested forms in Ruby on Rails using Cocoon gem. We will use two models, product and FAQ. The product can have multiple FAQs, which we will add manually while creating it.
1
gem "cocoon"
1
yarn add @nathanvda/cocoon
In app/javascripts/packs/application.js
:
1
2
3
// app/javascripts/packs/application.js
require("@nathanvda/cocoon")
Let’s do some database stuff.
1
2
3
rails g scaffold Product name price:integer
rails g model Faq question answer product:belongs_to
rails db:migrate
In app/models/product.rb
:
1
2
3
4
5
6
# app/models/product.rb
class Product < ApplicationRecord
has_many :faqs, inverse_of: :product
accepts_nested_attributes_for :faqs, reject_if: :all_blank, allow_destroy: true
end
In app/controllers/products_controller.rb
:
1
2
3
4
5
6
# app/controllers/products_controller.rb
def product_params
params.require(:product).permit(:name, :price, faqs_attributes: [:id, :question, :answer, :_destroy])
end
In app/views/products/_form.html.erb
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# app/views/products/_form.html.erb
<%= semantic_form_for @product do |f| %>
<% f.inputs do %>
<%= f.input :name %>
<%= f.input :price %>
<h3>FAQs</h3>
<div id='faqs'>
<%= f.semantic_fields_for :faqs do |faq| %>
<%= render 'faq_fields', :f => faq %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add faq', f, :faqs %>
</div>
</div>
<% f.buttons do %>
<%= f.submit 'Save' %>
<% end %>
<% end %>
<% end %>
Create a new partial app/views/products/_faq_fields.html.erb
:
1
2
3
4
5
6
7
8
9
# app/views/products/_faq_fields.html.erb
<div class='nested-fields'>
<%= f.inputs do %>
<%= f.input :question %>
<%= f.input :answer %>
<%= link_to_remove_association "remove faq", f %>
<% end %>
</div>
You’ll also need to make certain that jQuery is properly added to your project.