Rails 3.1 cocoon gem for nested forms - ruby-on-rails

I'm actually trying cocoon gem(by nathanvda) along with simple_form gem to dynamically add and remove fields on a form .I don't understand why the nested form doen't show up on my forms.Here's the code.(I'm newbie of course).Please can I have some help.
menu/_form.html.erb
<%= simple_form_for #menu do |f| %>
<%= f.input :name %>
<%= f.input :price %>
<%= f.simple_fields_for :drinks do |drink| %>
=render "drink_fields", :f => drink.links %>
<%= link_to_add_association "Add drink"%>
<%end%>
<%= f.button :submit %>
<%end%>
menu/_drink_fields.html.erb
.nested-fields
<%= f.input :name %>
<%= link_to_remove_association "remove drink", f %>
these are the models
class Drinks < ActiveRecord::Base
belongs_to :menu
end
class Menu < ActiveRecord::Base
attr_accessible :drinks_attributes
has_many :drinks, :dependent => :destroy
accepts_nested_attributes_for :drinks
end
in assets/javascripts/application.js
//= require cocoon
in layouts/application.html.erb
<%= javascript_include_tag :cocoon %>

Your nested form is wrong, you are mixing haml and erb. If you have no personal preference yet, I would recommend using haml, I find it much easier and cleaner than erb.
All that aside, your menu/_drink_fields.html.erb should look as follows:
<div class='nested-fields'>
<%= f.input :name %>
<%= link_to_remove_association "remove drink", f %>
</div>
Also, inside your menu/_form.html.erb you should write the following:
<%= f.simple_fields_for :drinks do |drink| %>
<%= render "drink_fields", f: drink %>
<% end %>
<%= link_to_add_association "Add drink", f, :drinks %>
Hope this helps.

Thanks for the head ups nathanvda.I finally find a gem to handle nested fields, Here is the link: https://github.com/lailsonbm/awesome_nested_fields.

Related

Gem Cocoon not rendering anything

I'm using Rails 6.0.2.2, Foundation, and wanted to do some nested forms using Cocoon. Here are my models:
class Adventure < ApplicationRecord
alias_attribute :pcs, :player_characters
has_many :player_characters, dependent: :destroy
accepts_nested_attributes_for :player_characters
end
class PlayerCharacter < ApplicationRecord
belongs_to :adventure
end
And here my views:
# _form.html.erb
<%= simple_form_for #adventure do |f| %>
<%= f.input :email %>
<%= f.input :test %>
<h3>PCs</h3>
<%= f.simple_fields_for :player_characters do |player_character| %>
<%= render 'player_character_fields', f: player_character %>
<% end %>
<div class='links'>
<%= link_to_add_association 'Add PC', f, :player_characters %>
</div>
<%= f.submit %>
<% end %>
# _player_character_fields.html.erb
<div class='nested-fields'>
<%= f.input :path %>
<%= f.input :race %>
<%= f.input :name %>
<%= f.input :player_name %>
<%= link_to_remove_association "remove PC", f %>
</div>
Neither the render nor the link_to display anything. I tried creating a different partial and if I render it outside of the simple_fields_for it works normally, but as soon as move it inside, it stops.
I tried all the solutions mentioned here https://github.com/nathanvda/cocoon/blob/master/app/assets/javascripts/cocoon.js:
create a file in app/javascript/src/cocoon.js
yarn add cocoon-js
yarn add github:nathanvda/cocoon#c24ba53
but nothing worked, and I didn't get any error messages in the console log.

Rails 5.1.4 fields_for for multiple objects

I have an Author and Book model. An Author can have many Book, but a Book can only have one Author.
During the creation of a new Author, how do I add a "New Book" button which will add a fields_for for the Author form? I want to be able to add more than one Book. So far, the solution that I have found is just to add a fixed number of fields_for, like this:
<%= form_with(model: author, local: true) do |form| %>
...
<% 5.times do %>
<%= form.fields_for :books do |books| %>
...
<% end %>
<% end %>
...
<% end %>
I do not want it to be like this, what if the author has more than 5 books? I want to be able to add books dynamically. Any solutions?
If you fine with adding a new dependency, there's cacoon gem, which allows you easier handle nested forms.
It's an additional dependency, but the code for adding a new associated record is simple as:
<%= form_for author do |f| %>
...
<%= f.fields_for :books do |book| %>
<%= render 'book_fields', f: book %>
<%= link_to_add_association 'add book', f, :books %>
<%end%>
author.rb
accepts_nested_attributes_for :books,
:allow_destroy => true,
:reject_if => :all_blank
In your view file
<div class="bank_account_details">
<%= f.fields_for :bank_account_details do |builder| %>
<p>
Book: <%= builder.text_field :name %>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, "Remove Book" %>
</p>
<% end %>
<div>
<%= link_to_add_fields "Add Book", f ,:books %>
In your controller add parameters
params.require(:author).permit(:name, books_attributes: [:id, :name, :_destroy])

edit associated model by input form?

Order has_many jobs
Job belongs to order
And I want to edit attributes of #job.order:
<% order = #job.order %>
<%= simple_form_for [#job, order],
url: job_path(#job),
method: :put,
remote: true do |f| %>
<%= f.input :order_status, input_html: {class: 'form-control'} %>
(...)
<% end %>
any way to do it by just using input in simple form?
in job.rb
accepts_nested_attributes_for :order
in form.html.erb
simple_form_for #job do |f|
f.simple_fields_for #job.order do |order_form|
order_form.input :status
end
end
in jobs_controller.rb
params.require(:job).permit(:something, :something_else, :order_attributes => [:status])
You can use the excellent Cocoon gem https://github.com/nathanvda/cocoon to manage nested relationships, including the ability to easily add new nested relationships.
class Job < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders, reject_if: :all_blank, allow_destroy: true
end
class Order < ActiveRecord::Base
belongs_to :job
end
Note the pluralization.
_form.html.erb*
<%= form_for #job do |f| %>
<%= f.label :job_name %>
<%= f.text_field :name %>
<div id='order'>
<%= f.fields_for :orders do |order| %>
<%= render 'order_fields', f: order %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add order', f, :orders %>
</div>
<%= f.submit %>
<% end %>
_order_fields.html.erb partial
<div class='nested-fields'>
<%= f.label :order_name %>
<%= f.text_field :order_name %>
</div>
<%= link_to_remove_association "remove order", f %>

Rails 4 - set display value when editing autocomplete nested fields_for

I'm developing a form that links recipes, recipe_entries (has_many_though join table) and ingredients with jQuery autocomplete in Rails 4. I'm using a combination of of the simple_form, cocoon and rails4-autocomplete gems. The idea is that users can create a recipe and dynamically add and edit associated ingredients via autocomplete (the quantity for each ingredient is stored on the join table).
I have most functionality working, however the only issue that still bugs me is that I had to create an f.input for :ingredient that when editing the recipe shows values, such as the below image and not the desired name of the associated ingredient.
Other than that, I can dynamically create, delete and update all ingredient associations. Any tips are much appreciated. Here my code:
Gemfile
gem 'rails', '4.0.2'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'simple_form'
gem "cocoon"
gem 'rails4-autocomplete'
Recipe.rb
class Recipe < ActiveRecord::Base
has_many :recipe_entries, :dependent => :destroy
has_many :ingredients, through: :recipe_entries
accepts_nested_attributes_for :recipe_entries,:allow_destroy => true
accepts_nested_attributes_for :ingredients
end
RecipeEntry.rb
class RecipeEntry < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
end
Ingredient.rb
class Ingredient < ActiveRecord::Base
has_many :recipe_entries
has_many :recipes, through: :recipe_entries
end
Recipes form:
<%= simple_form_for(#recipe) do |f| %>
<% if #recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
<ul>
<% #recipe.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.input :name %>
<%= f.input :description %>
<div id="recipe_entries">
<%= f.simple_fields_for :recipe_entries, :input_html => { :class => "form_inline" } do |entry|%>
<% render 'recipe_entry_fields', :f => entry %>
<% end %>
<%= link_to_add_association 'add recipe entry', f, :recipe_entries%>
</div>
<%= f.button :submit %>
<% end %>
recipe_entry_partial
<div class="nested-fields">
<% #it=f.options[:child_index] %>
<%= f.input :ingredient_id, as: :hidden, input_html: {id: "ingredient_id#{#it}"} %>
<%= f.input :ingredient, :url => autocomplete_ingredient_name_recipes_path, :as => :autocomplete, :input_html => {id_element: "#ingredient_id#{#it}"}, placeholder: "Enter ingredient..." %>
<%= f.input :quantity %>
<%= link_to_remove_association "remove entry form", f %>
</div>
Update
I believe that the easiest way of solving the edit display issue is to pre-insert the correct value in the f.input containing the autocomplete. e.g.
<%= f.input :ingredient, :url => autocomplete_ingredient_name_recipes_path, :as => :autocomplete, :input_html => {id_element: "#ingredient_id#{#it}", value: f.object.ingredient.name}, placeholder: "Enter ingredient..." %>
Unfortunate, this only works up to the recipe entries association. This means that I can still get values for e.g. f.object.ingredient_id which returns the correct result. However, I can't get the associated ingredient any more. I seem to be able to get the associated ingredient but when I try to e.g. call the .name method on it, I receive a nil error.
Strangely, I can get the ingredient_id by calling f.object.ingredient_id and can retrieve an Ingredient from the Model by calling e.g. Ingredient.get(1).name. BUT, I cannot dynamically link the two values. Ingredient.get(f.object.ingredient_id) returns a nil error. Also with to_string or to_integer calls.
OK, the solution to a full autocomplete within the nested form is as follows:
<div class="nested-fields">
<% #it=f.options[:child_index] %>
<%= f.input :ingredient_id, as: :hidden, input_html: {id: "ingredient_id#{#it}"} %>
<%= f.simple_fields_for :ingredients, f.object.ingredient do |ii| %>
<%= ii.input :name, :url => autocomplete_ingredient_name_recipes_path, :as => :autocomplete, :input_html => {id_element: "#ingredient_id#{#it}"}, placeholder: "Enter ingredient..." %>
<% end %>
<%= f.input :quantity %>
<%= link_to_remove_association "remove entry form", f %>
</div>
The trick was to place the f.input autocomplete within another fields_for tag and make sure to specify the context for each recipe_entry with a f.object.ingredient. Other than this partial, I didn't have to make any other changes!

No errors and no output for rails cocoon gem

I am working on a dynamically nested form using the cocoon gem. I have two models
class CrossTable < ActiveRecord::Base
attr_accessible :title, :table_name, :database, :folder_label_id, :foreign_fields_attributes
belongs_to :folder_label
has_many :foreign_fields
accepts_nested_attributes_for :foreign_fields
validates :title, :table_name, :database, :folder_label_id, presence: true
end
class ForeignField < ActiveRecord::Base
attr_accessible :cross_table_id, :column_name, :description
belongs_to :cross_table
has_many :filter_sets
end
I have cocoon and jquery-rails in the gemfile
I added //=require cocoon to the application.js file
And here is my form partial
<%= simple_form_for #table do |f| %>
<%= f.input :title %>
<%= f.input :folder_label_id, :collection => #folders, :label_method => :title, :value_method => :id %>
<br><br>
<%= f.input :table_name %>
<%= f.input :database %>
<%= f.simple_fields_for :foreign_fields do |fields| %>
<%= render 'foreign_field_fields', :f => fields %>
<div id='links'>
<%= link_to_add_association 'Add Field', f, :foreign_fields %>
</div>
<% end %>
<%= f.button :submit %>
<% end %>
#table is an instance of the cross table model. Nothing in the foreign_field_fields partial shows up and link_to_add_association does nothing, and I get no errors. How can I start debugging this? Does anyone spot an error?
You wrote the link_to_add_association inside the simple_fields_for, which will loop over all :foreign_fields and execute the given block. So if there are no foreign-fields yet, the link_to_add_association is never shown.
You should write your view as follows (as documented):
<%= simple_form_for #table do |f| %>
<%= f.input :title %>
<%= f.input :folder_label_id, :collection => #folders, :label_method => :title, :value_method => :id %>
<br><br>
<%= f.input :table_name %>
<%= f.input :database %>
<%= f.simple_fields_for :foreign_fields do |fields| %>
<%= render 'foreign_field_fields', :f => fields %>
<% end %>
<div id='links'>
<%= link_to_add_association 'Add Field', f, :foreign_fields %>
</div>
<%= f.button :submit %>
<% end %>
Hope this helps.

Resources