edit associated model by input form? - ruby-on-rails

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 %>

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.

Cocoon First Option Not Saving - Nested Fields

I'm using Cocoon for a nested form, however the first set of fields do not save into the database, if I create a second row they seem to save just fine?
I'm guessing its just something I'm overlooking
class Form < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions, :reject_if => :all_blank, :allow_destroy => true
end
class Question < ActiveRecord::Base
belongs_to :form
end
----- form_controller.rb
def new
#form = Form.new
#form.questions.build
end
def create
#form = Form.new(form_params)
if #form.save
redirect_to action: "show", id: #form.id
else
render('new')
end
end
def form_params
params.require(:form).permit(:title, :description, :status, questions_attributes: [:form_id, :question_type, :question_text, :position, :answer_options, :validation_rules, :done, :_destroy])
end
<%= simple_form_for Form.new ,:url => {:action => :create} do |f| %>
<div class="section-row">
<div class="section-cell">
<%= f.label :title, "Form Title" %>
<%= f.text_field :title, placeholder: "Form Title" %>
<br/></br>
<%= f.label :description, "Form Description" %>
<%= f.text_area :description, placeholder: "Form Description" %>
<%= f.hidden_field :status, value: "online" %>
</div>
</div>
<div class="section-row">
<div class="section-cell">
<div id="questions">
<%= simple_fields_for :questions do |question| %>
<%= render 'question_fields', :f => question %>
<%= link_to_add_association 'add question', f, :questions %>
<% end %>
</div>
</div>
</div>
<div class="section-row">
<div class="section-cell">
<%= f.submit "Create Ticket", class: "btn btn-primary btn-lg" %>
</div>
</div>
<% end %>
---- _question_fields.html.erb
<div class='nested-fields'>
<%= f.label :question_type, "Question Type" %>
<%= f.select :question_type,
options_for_select([['Text Box','textbox'],['Dropdown Options','select'], ['Mutiple Choice','radio']], params[:question_type]),
{}, { :class => '' } %>
</div>
You forgot the f in front of the simple_fields_for : then the simple_fields_for has no knowledge of the form, nor the associations, so it will name the parameters posted to the controller differently, so it will be blocked by your strong parameters definition.
So if you write
f.simple_fields_for :questions do |question|
it should just work ;)
Smaller remarks:
the link_to_add_association should be outside of the loop, otherwise it will not be visible if there are none, and will be displayed for each question (which may or may not make sense in your UI).
you should add the id inside the strong parameters for questions_attributes (important for editing/deleting)
You wrote the link_to_add_association inside the simple_fields_for
you should write your form as follows (as documented):
<div id="questions">
<%= f.simple_fields_for :questions do |question| %>
<%= render 'question_fields', f: => question %>
<% end %>
<div class="links">
<%= link_to_add_association 'add task', f, :questions %>
</div>

nested forms and cocoon. undefined method `label' for nil:NilClass

Hi all. When I open /courses/new (or /courses/some_id/edit), browser returns this error:
Showing /app/views/dashboard/courses/_price.html.erb where line #1 raised:
undefined method `label' for nil:NilClass
Here are codes, _form.html.erb:
<%= simple_form_for [:dashboard, #course], html: { multipart: true } do |f| %>
//////
<%= f.fields_for :prices do |p|%>
<%= render 'price', :f => 'prices' %>
<% end %>
<%= link_to_add_association 'Add', f, :prices %>
////////
_price.html.erb:
<%= p.label :price %>
<%= p.text_field :price %>
<%= p.label :desc %>
<%= p.text_field :description %>
<%= link_to_remove_association "remove", f %>
Models:
class Price < ActiveRecord::Base
belongs_to :course
end
class Course < ActiveRecord::Base
has_many :prices
accepts_nested_attributes_for :prices, :reject_if => :all_blank, :allow_destroy => true
end
How resolve this error? And why it has arisen?
You are using simple_form_for,so i guess this line
<%= f.fields_for :prices do |p|%>
should be
<%= f.simple_fields_for :prices do |p|%>
Have a look at the Git for more Info.
In your _price.html.erb partial view, your are using a form builder that does not exists (is nil) because you did not pass it as argument:
# _price.html.erb
<%= p.label :price %>
#^ the variable `p` is the form builder here
To solve this problem, you have to pass the form builder to the partial view, like this:
<%= f.fields_for :prices do |p| %>
<%= render 'price', :f => 'prices', p: p %>
#^^^^ We pass the variable `p` (form builder) to the partial
<% end %>
Hope this helps!

Rails - :_destroy method not working

I am trying to use :_destroy method in a nested form, but it just does not work
There are two models:
class Setting < ActiveRecord::Base
attr_accessible :category, :name, :setting_items_attributes, :_destroy
attr_accessor :_destroy
has_many :setting_items, :dependent => :destroy
accepts_nested_attributes_for :setting_items, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
class SettingItem < ActiveRecord::Base
attr_accessible :setting_id, :value
belongs_to :setting
end
In the controller I create a instance:
def edit
#setting = Setting.find(params[:id])
#setting.setting_items.build
end
And the form looks like this:
<%= form_for(#setting) do |f| %>
<div class="field">
<%= f.label :category %>
<%= f.text_field :category %>
</div>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<hr>
<h3>Params:</h3>
<%= f.fields_for :setting_items do |s| %>
<span>
<div class="fields">
<%= s.text_field :value %>
<%= s.hidden_field :_destroy %>
<%= link_to_function "delete", "remove_fields(this)"%>
</div>
<% end %>
<div class="actions">
<%= f.submit "Update", :class => "btn btn-primary"%>
</div>
<% end %>
Also the function I use is here:
function remove_fields(link){
$(link).prev("input[type=hidden]").val("1");
$(link).parent().fadeOut("slow");
}
So the setting_items form is simply not working at all, It shows the update is successful, but nothing is actually added or deleted.
for example->your model associations are as follows: just follow the below steps to make use of magical _destroy attribute
####parent model
plan.rb
has_many :members,:dependent => :destroy
#this is important you want to destroy nested records
accepts_nested_attributes_for:members,:allow_destroy => true
attr_accessible :members_attributes
##child model
member.rb
belongs_to :plan
######controller
def edit
#plan.Plan.find(params[:id])
end
#####edit.html.erb
<%= form_for #plan do |f| %>
<%= f.fields_for :members do |member| %>
<div class="member">
<%= member.text_field :title%>
<%= image_tag 'delete.png',:class =>'remove_member',:id=>member.id %>
<!-- we need to set this hidden field value as 1 to mark it to be deleted during save/update of parent-->
<%= member.hidden_field :_destroy, :class => 'delete_member', :member_id => member.id %>
<!--similar to
<input id="plan_members_attributes_0__destroy" class="delete_member" type="hidden" value="false" name="plan[members_attributes][0][_destroy]" member_id="#{id of member}">
-->
</div>
<%end%>
<%end%>
##add js onclick of remove button/image
$('.delete_member').click(function(){
//remove div from screen
$(this).closest('.member').remove();
//get relevant id to remove/mark as delete
id =jQuery(this).attr('id');
//remove/mark the nested model/record as ready for deletion for rails by adding true/1 value
$("input[member_id="+id+"]").attr('value',1);
})

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