Nested form isn't saved - ruby-on-rails

I am using the gem Cocoon for nested form and this form don't get submitted...
What am I doing wrong please? Thank u
_form.html.erb
<div class="container">
<div class="row">
<%= simple_form_for #event do |f| %>
<div class="col-xs-12">
<h3>Your event to share</h3>
<%= f.input :name, label: "Event's name" %>
<%= f.input :total_price, label: "What is the total price" %>
<h3> Add your friends to share the bill</h3>
<div id="participants">
<%= f.simple_fields_for :participants do |participant| %>
<%= render "participants_fields", f: participant %>
<% end %>
<div class="links">
<%= link_to_add_association "add a friend", f, :participants, partial: "participants_fields", class:"btn btn-primary" %>
</div>
</div>
<%= f.button :submit %>
</div>
<% end %>
</div>
</div>
_participants_fields.html.erb
<div class="nested-fields">
<%= f.input :first_name, label: "Enter your friend's first name" %>
<%= f.input :salary, label: "Enter his/her monthly pay" %>
<div class="links">
<%= link_to_remove_association "Remove this friend", f , class: "btn btn-danger btn-xs" %>
</div>
</div>

I used this tutorial to implement nested forms with cocoon gem just few hours ago. You might find it useful. https://www.youtube.com/watch?v=56xjUOAAZY8
To get a strong understanding of how to create a nested form you should also see this video on how to do it without a gem. https://www.youtube.com/watch?v=pulzZxPkgmE

I was missing this relation
has_many :participants, inverse_of: :event
I add has_many :participants, dependent: :destroy

Related

link_to_remove_association: undefined method `new_record?' for nil:NilClass

I'm trying to build 2 nested forms with Cocoon which works fine. I have a Game model which has many Questions and a Question has many Answers.
Models
# Game model
class Game < ApplicationRecord
has_many :questions, dependent: :destroy
accepts_nested_attributes_for :questions, allow_destroy: true
end
# Question model
class Question < ApplicationRecord
belongs_to :game
has_many :answers, dependent: :destroy
validates :text, presence: true
accepts_nested_attributes_for :answers, allow_destroy: true
end
# Answer model
class Answer < ApplicationRecord
belongs_to :question
end
the link_to_add_association link works everywhere, the link_to_remove association link works fine in _question_fields partial view but I have
`"undefined method `new_record?' for nil:NilClass"`
error when I insert the link_to_remove_association in _answer_fields partial view. I'm sure that it's an error on my part but I can't retrieve where.
error
Views
new.html.erb
<%= form_with(model: #game, url: games_path, local: true ) do |form| %>
<div class="form-group game">
<%= form.label(':name', "Title") %>
<%= form.text_field ':name', class: 'form-control form-control-sm' %>
</div>
<div class="wrapper-questions"></div>
<%= form.fields_for :questions do |question_form| %>
<%= render 'games/partials/question_fields', f: question_form %>
<% end %>
<div class="row form-actions links">
<div class="col-sm">
<%= link_to_add_association 'Add a question',
form,
:questions,
:partial => 'games/partials/question_fields',
class: "btn btn-secondary",
'data-association-insertion-node' => '.wrapper-questions'
%>
</div>
<div class="col-sm text-right">
<%= form.submit 'Save', :class => "btn btn-primary" %>
</div>
</div>
<% end %>
partials/_question_fields.html.erb
<div class="question-wrapper jumbotron nested-fields">
<%= link_to_remove_association f, { class: 'btn btn-light' } do %>
<i class="fa fa-trash" aria-hidden="true"></i> Delete the question
<% end %>
<p><strong>Question</strong></p>
<div class="form-group">
<strong><%= f.label(:text, 'Question:') %></strong>
<%= f.text_field :text, class: "form-control" %>
</div>
<%= f.fields_for :questions do |answer_form| %>
<%= render 'games/partials/answer_fields', f: answer_form %>
<% end %>
<div class="row">
<div id="wrapper-answers"></div>
<div class="col-sm">
<%= link_to_add_association 'Add an answer',
f,
:answers,
:partial => 'games/partials/answer_fields',
data: { 'association-insertion-method' => :prepend },
class: "btn btn-secondary"
%>
</div>
</div>
</div>
partials/_answer_fields.html.erb
<div class="row nested-fields">
<div class="col">
<%= f.text_field :text, class: "form-control" %>
</div>
<div class="col">
<label class="btn btn-secondary form-control">
<%= f.check_box :correct %>
</label>
</div>
<!-- My error is here -->
<%= link_to_remove_association 'remove answer', f %>
</div>
Does anybody have an idea what I'm doing wrong ?
Regards,
Lilith
In partials/_question_fields.html.erb
<%= f.fields_for :questions do |answer_form| %>
Should likely be :
<%= f.fields_for :answers do |answer_form| %>

Rails: Saving Parent and Child simultaneously with nested forms

I have an Event model and a Packages model:
# event.rb
belongs_to :organization, optional: true
belongs_to :event_type, optional: true
has_many :packages
has_many :collaborations
has_many :messages, through: :collaborations
has_many :forms, through: :collaborations
# package.rb
belongs_to :event
has_many :package_collaborations
has_many :collaborations, through: :package_collaborations
I want the user to be able to create an Event and Packages at the same time with a nested form like this:
These are my two forms:
#_event_form.rb (simplified for easier reading)
<%= form_for(event) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<br>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<% if f.object.new_record? %>
<%= f.hidden_field :status, value: 'upcoming' %>
<% else %>
<div class="form-group">
<%= f.label :attendee_count %>
<%= f.number_field :attendee_count, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :status %>
<%= f.select :status, [['Upcoming','upcoming'],['Completed','completed']], {}, class: 'form-control' %>
</div>
<% end %>
<hr>
<div class="form-group required">
<%= f.label :started_at, 'Starts' %>
<div class='input-group date form_datetime'>
<% if event.started_at.present? %>
<%= f.text_field :started_at, class: 'form-control', value: event.started_at.strftime("%m/%d/%Y %H:%M %p") %>
<% end %>
</div>
</div>
<div class="form-group required">
<%= f.label :ended_at, 'Ends' %>
<div class='input-group date form_datetime'>
<% if event.ended_at.present? %>
<%= f.text_field :ended_at, class: 'form-control', value: event.ended_at.strftime("%m/%d/%Y %H:%M %p") %>
<% end %>
</span>
</div>
</div>
<%= f.hidden_field :platform_type, value: "a_platform" %>
<hr>
<%= render 'packages/package_form', event: #event %> # <--- Nested form here.
<div class="actions" id="listen-for-hover">
<%= f.submit 'Save', class: 'btn btn-primary', :id => "event-create-button" %>
</div>
<% end %>
#_package_form.rb
<%= form_for([#event, #package]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :kind, value: params[:kind] if f.object.new_record? %>
<div class="form-group required">
<%= f.label :Your_offer_?, "Your Offer?" %>
<%= f.text_area :offering, class: 'form-control', :placeholder => "e.g. Your logo on stuff" %>
</div>
<div class="form-group">
<%= f.label :notes %>
<%= f.text_area :notes, class: 'form-control', :placeholder => "Notes here" %>
</div>
<hr>
<div class="actions">
<%= f.submit 'Submit', class: 'btn btn-primary', id: 'package-submit-button', disabled: true %>
</div>
<% end %>
Using the form this way results in this error:
Extracted source (around line #3):
1 <%# remoteFlag = false %>
2 <%# remoteFlag = true if #event.title == "dummy event" %>
3 <%= form_for([#event, #package]) do |f| %>
4 <%= render 'shared/error_messages', object: f.object %>
Obviously this is because #event hasn't been created yet so there isn't an ID for it. What would be the best way to make this nested form that is used to make new Event/Packages (new Objects with no ID) at the same time or Edit existing (Existing objects with IDs) ones by using the partial in another part of the app?
You need to add
accepts_nested_attributes_for :package
to your Event model (in event.rb). Then, in the 'new' method of your events controller, add
#package = #event.packages.build
In your form, you will need to use the fields_for method. There is an excellent Railscast on this whole process here: http://railscasts.com/episodes/196-nested-model-form-part-1
If you're not familiar with Ryan Bates' Railscasts, I highly recommend you spend some time with them.
You can use the 'build' method for creating an empty 'package' in your 'event'. There is an example on the official RoR guides
E.g.
<%= form_for([#event, #event.packages.build]) do |f| %>

Rails 4 simple Quiz web app using Cocoon

My current task is to create simple Quiz web app. App will be structured this way:
- Admin can create, edit, delete and activate quizzes.
- Visitors can take a quiz and submit it. Then receiving quiz results etc.
So far I have created nested form (with Cocoon gem) where admin can create quiz's and add new questions and possible answers, but I have not a single idea how to make that nested form as submit-able quiz for visitors.
My code:
Form:
<%= form_for [:admin, #test] do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %>
<br/>
<%= f.text_field :description %>
</div>
<h3>Questions</h3>
<div id="question">
<%= f.fields_for :questions do |question| %>
<%= render 'admin/question_fields', f: question %>
<% end %>
<div class="links">
<%= link_to_add_association 'add question', f, :questions %>
</div>
</div>
<%= f.submit %>
<% end %>
_question_fields partial:
<div class="nested-fields">
<div class="field">
<%= f.label :description %>
<br/>
<%= f.text_field :description %>
</div>
<%= link_to_remove_association "remove question", f %>
<h3>Answers</h3>
<div id="answers">
<%= f.fields_for :answers do |answer| %>
<%= render 'admin/answer_fields', f: answer %>
<% end %>
<div class="links">
<%= link_to_add_association 'add answer', f, :answers %>
</div>
</div>
</div>
Question: What is the best way to allow dynamic nested form to be used for taking tests by visitors and store submitted data in database?
Thanks in advance.!

Nested form two levels deep in Rails for selecting seeded objects

I am trying to build in a form a nested form going two levels deep. It's about creating a factory. Both the first and the second level are a collection_check_boxes to select seeded objects.
Relations in words
To the first level I had it working and concretely that momentarily looks like:
A factory has many machines, through handles.
Then I wanted to add an association to the machines in the same form:
A machine has many materials, through feeds.
A factory model looks like:
validates :name, presence: true
validates :description, presence: true
# Factory to handle machines.
has_many :handles, :dependent => :destroy
has_many :machines, :through => :handles
# Factory needs to know about materials (fed through machines).
accepts_nested_attributes_for :machine
And the machine model is logically derived from this, but without the nested attributes for materials of course. (Materials is an endpoint here.)
Then the controller part for the form to create the factory (factory_controller.rb):
def factory_params
params.require(:factory).permit(:name, :description,
:machine_ids => [], machines: [:material_ids => [] ])
end
#materials also exists in the relevant actions.
and the form looks like:
<div class="w3-row">
<div class="w3-twothird" style="margin-left: 16.65%">
<%= simple_form_for #factory do |f| %>
<!-- Input -->
<%= f.input_field :name %>
<%= f.label :name %>
<%= f.error :name %>
<%= f.input_field :description, rows: 7 %>
<%= f.label :description %>
<%= f.error :description %><br><br>
<div class="w3-row w3-margin-top">
<!-- Machines card -->
<div class="w3-third w3-card w3-padding-bottom">
<h5 class="w3-text-teal w3-center">Machines</h5>
<ul class="w3-ul" id="machines">
<%= f.collection_check_boxes :machine_ids, #machines, :id, :name do |b| %>
<li>
<%= b.label do %>
<%= b.check_box class: "w3-check" %>
<%= b.text %>
<% end %>
</li>
<% end %>
</ul>
</div>
<!-- Materials card -->
<div class="w3-third w3-card w3-padding-bottom">
<h5 class="w3-text-teal w3-center">Machines</h5>
<ul class="w3-ul" id="materials">
<%= f.collection_check_boxes :material_ids, #materials, :id, :sort do |b| %>
<li>
<%= b.label do %>
<%= b.check_box class: "w3-check" %>
<%= b.text %>
<% end %>
</li>
<% end %>
</ul>
</div>
</div>
<br><br>
<!-- Zenden -->
<div class="w3-center w3-margin-bottom">
<%= f.button :button, class: "w3-btn w3-blue w3-center" %>
</div>
<% end %>
</div>
</div>
Sorry for all the super irrelevant css.
My spec says:
Users can create new factory with associated materials on the associated machines
Failure/Error: <%= b.check_box class: "w3-check" %>
ActionView::Template::Error:
undefined method `material_ids' for #<Factory:0x007fb3f41fbad0>
You should use fields_for method to manage associated fields in a form,
try below code :
<div class="w3-row">
<div class="w3-twothird" style="margin-left: 16.65%">
<%= simple_form_for #factory do |f| %>
<!-- Input -->
<%= f.input_field :name %>
<%= f.label :name %>
<%= f.error :name %>
<%= f.input_field :description, rows: 7 %>
<%= f.label :description %>
<%= f.error :description %><br><br>
<div class="w3-row w3-margin-top">
<!-- Machines card -->
<div class="w3-third w3-card w3-padding-bottom">
<h5 class="w3-text-teal w3-center">Machines</h5>
<ul class="w3-ul" id="machines">
<%= f.collection_check_boxes :machine_ids, #machines, :id, :name do |b| %>
<li>
<%= b.label do %>
<%= b.check_box class: "w3-check" %>
<%= b.text %>
<% end %>
</li>
<% end %>
</ul>
</div>
<!-- Materials card -->
<% f.fields_for #machines do |ff| %>
<div class="w3-third w3-card w3-padding-bottom">
<h5 class="w3-text-teal w3-center">Machines</h5>
<ul class="w3-ul" id="materials">
<%= ff.collection_check_boxes :material_ids, #materials, :id, :sort do |b| %>
<li>
<%= b.label do %>
<%= b.check_box class: "w3-check" %>
<%= b.text %>
<% end %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<br><br>
<!-- Zenden -->
<div class="w3-center w3-margin-bottom">
<%= f.button :button, class: "w3-btn w3-blue w3-center" %>
</div>
<% end %>
</div>
</div>

Rails - Cocoon gem - Nested Forms

I am trying to make an app with Rails 4.
I use simple form gem for forms and am trying to use Cocoon gem for nested elements of the forms.
I asked this question, which explains what I'm trying to achieve in more detail: Rails - Multiple entries for a single attribute
I have a profile model and a qualifications model. The associations are:
profile.rb
has_many :qualifications
accepts_nested_attributes_for :qualifications, reject_if: :all_blank, allow_destroy: true
qualification.rb
belongs_to :profile
the profiles controller includes the qualification attributes in the strong params:
def profile_params
params[:profile].permit(:user_id, :title, :hero, :overview, :research_interest, :occupation, :external_profile,
:working_languages, :tag_list,
qualifications_attributes: [:id, :level, :title, :year_earned, :institution, :_destroy] )
end
My profile form now has:
<div class="intpol2">
Your qualifications
</div>
<%= render 'qualifications/qualification_fields', f: f %>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_add_association 'Add a qualification', f: f, partial: 'qualifications/qualification_fields' %>
</div>
My qualifications partial form is now named in my qualification views folder as _qualifications_fields.html.erb
<div class="nested-fields">
<div class="container-fluid">
<%= simple_fields_for :qualifications do |f| %>
<div class="form-inputs">
<div class="row">
<div class="col-md-6">
<%= f.input :title, :label => "Your award" %>
</div>
<div class="col-md-6">
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.input :level, collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
</div>
<div class="col-md-6">
<%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year) %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<!-- link_to_remove_association 'Remove this qualification', f, :f -->
</div>
</div>
</div>
<% end %>
</div>
</div>
I commented out the remove link, because as is, I get this error:
undefined method `new_record?' for nil:NilClass
I'm baffled by the way Rails reports errors- I rarely understand error messages of this style, but I gather it's something to do with there not being any qualifications to remove. Does cocoon handle this?
When I comment this out and try again, I get this error with the link to add an association:
undefined method `object' for #<Hash:0x007fe70c501ea0>
I don't know what this message means either.
So, by following the steps in the Cocoon gem docs, (with changes because I don't know how to write things in haml; and changing the form of expression to reference the form builder 'f: f' works across the rest of my forms, so Im guessing that the expression shown in the docs might be something to do with haml), I have 2 errors at this stage:
add association - undefined method object
remove association - undefined method `new_record?
I'm struggling to understand what's going on here.
TAKING JEIWAN'S SUGGESTION:
I change my profile form to:
<%= simple_form_for #profile, html: { multipart: true } do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<div class="row">
<div class="intpol2">
Your professional qualifications
</div>
<%= simple_fields_for :qualifications do |f| %>
<%= render 'qualifications/qualification_fields', f: f %>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_add_association 'Add a qualification', f, :qualifications, partial: 'qualifications/qualification_fields' %>
<% end %>
</div>
</div>
<div class="form-actions">
<%= f.button :submit, "Submit", :class => 'formsubmit' %>
</div>
<% end %>
</div>
</div>
</div>
I change my qualification fields form to:
<div class="nested-fields">
<div class="container-fluid">
<div class="form-inputs">
<div class="row">
<div class="col-md-6">
<%= f.input :title, :label => "Your award" %>
</div>
<div class="col-md-6">
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.input :level, collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
</div>
<div class="col-md-6">
<%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year) %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_remove_association 'Remove this qualification', f %>
</div>
</div>
</div>
</div>
</div>
When I save this and try again, I get this error:
undefined method `new_record?' for nil:NilClass
The error message highlights this line:
<%= link_to_remove_association 'Remove this qualification', f %>
link_to_add_association 'Add a qualification', f: f, partial: 'qualifications/qualification_fields'
f: f is incorrect here. The second parameter should be a form builder (just an object, not a hash) and the third parameter – the name of the association, i.e. :qualifications in your case. So it should look like this:
link_to_add_association 'Add a qualification', f, :qualifications, partial: 'qualifications/qualification_fields'
And here:
link_to_remove_association 'Remove this qualification', f, :f
:f is also wrong. Third parameter here is HTML options. If you don't need them, then just specify 2 parameters:
link_to_remove_association 'Remove this qualification', f
Next, _qualification_fields.html.erb shouldn't contain simple_fields_for. This partial is used to render the fields of one distinct association object. It is shown when you click 'Add a qualification' or when your parent object already has some qualifications. simple_fields_for :qualifications should be put in you profile form and contain render 'qualifications/qualifications_fields', f: f and link_to_add_association .... Consider this example: https://github.com/nathanvda/cocoon#simpleform

Resources