I am getting the error
ActionView::Template::Error (undefined method `values_at' for nil:NilClass):
when using nested_form gem
Here is my code
Models
class Poll < ActiveRecord::Base
attr_accessible :question, :poll_answers_attributes
has_many :poll_answers
accepts_nested_attributes_for :poll_answers
end
class PollAnswer < ActiveRecord::Base
belongs_to :poll
attr_accessible :answer
end
View
=nested_form_for [:admin, #poll], mutipart: true, class: "form-horizontal" do |f|
.span6
.control-group
=f.label :question, class: "control-label"
.controls
=f.text_field :question, rows: "5", class: "span5"
= f.link_to_add "Add a Answer", :poll_answers
=f.submit "Create Post", class: "btn btn-primary"
StackTrace
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/builder_mixin.rb:41:in `block in link_to_add'
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/view_helper.rb:53:in `call'
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/view_helper.rb:53:in `after_nested_form_callbacks'
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/view_helper.rb:8:in `block in nested_form_for'
Any Ideas ?
As mentioned in the documentation for the nested_form gem, you have to mention the field_for of the nested object before link_to_load button. I haven't use this gem previously but after going through the documentation, i am guessing this.
Here the form looks like
<%= nested_form_for [:admin, #poll], mutipart: true, class: "form-horizontal" do |f| %>
<%= f.text_field :question %>
<%= f.fields_for :poll_answers do |poll_ans_form| %>
<%= poll_ans_form.text_field :name %>
<%= poll_ans_form.link_to_remove "Remove this task" %>
<% end %>
<p><%= f.link_to_add "Add a Answer", :poll_answers %></p>
<% end %>
You should check out simple_form for doing this type of nested form. It makes it pretty easy. Based on your models you posted, something like this should work:
# controller
def new
#poll = Poll.new
end
# new.html.erb
<%= simple_form_for #poll do |f| %>
<%= f.simple_fields_for :poll_answer do |l| %>
<%= l.input :answer, autofocus: true %>
<%= l.submit "Add", class: 'small round button' %>
<% end %>
<% end %>
Then that post should get sent to the poll#create controller if you have the route open. From there, you can work your logic on it.
Hope that helps.
Related
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.
Job belongs_to :order
Order has_many :jobs
Job accepts_nested_attributes_for :order
Form to edit notes doesn't show up. Why?
<% order = #job.order %>
<%= simple_form_for #job,
url: admin_job_path(#job),
method: :put,
remote: true do |f| %>
# (...) fields for #job do show up normally
# can't see the field below:
<% f.simple_fields_for order do |form| %>
<%= form.input(
:notes,
input_html:
{
value: (order.notes),
rows: 7,
class: 'form-control'
}
)
%>
<% end %>
<br/>
<%= f.button :submit, :class => "btn btn-success btn-sm" %>
<% end %>
Adding some text because "it's mostly code". I hope the answer is clear without too much elaboration, but can always add more datails if you need. Thank you for any help!
Form to edit notes doesn't show up. Why?
You are missing = here <% f.simple_fields_for order do |form| %>. It should be
<%= f.simple_fields_for order do |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 %>
I am trying to build a form with nested resources in my rails 4 app. I am using the cocoon gem. Each step will have substeps, and I'd like to allow the user to add as many substeps to the form and he/she would like.
Step.rb
class Step < ActiveRecord::Base
has_many :substeps
accepts_nested_attributes_for :substeps
Substep.rb
class Substep < ActiveRecord::Base
belongs_to :step
form code
<%= form_for :step, :url => steps_path do |f| %>
<%= text_field(:step, :title, :value => '', class: 'fly-input input_info', placeholder: 'Process Title', id: 'step_form_title') %>
<%= text_field(:step, :description, :value => '', class: 'fly-input input_info', placeholder: 'Process Description', id: 'step_form_description') %>
<%= hidden_field :step, :known %>
<%= hidden_field_tag :experiment, #experiment.id %>
<%= f.fields_for :substep do |ff| %>
<%= ff.text_field :description %>
<% end %>
<%= link_to_add_association 'Add substep', f, :substeps %>
<%= f.submit "Done", class: "main_button" %>
<% end %>
When I do this, I get an error reading:
"undefined method `reflect_on_association' for NilClass:Class" on this line
<%= link_to_add_association 'Add substep', f, :substeps %>
Any thoughts on my problem?
EDIT
Changed text_field to ff.text_field based on Pavan's suggestion
Cocoon expects that you provide a form object as second parameter, as you do, but also expects that this second parameter will have actually Rails model instance as attribute f.object.
Your form is created just with model name so form_for :step so Cocoon raises an exception.
To solve this you should change it to form_for #step where #step can be Step.new or any other Step instance.
I have a model
class Rcomment < ActiveRecord::Base
attr_accessible :comment, :rating
belongs_to :recipe
belongs_to :user
end
I'm trying to add comment via the show view of recipe. I populated rcomment table with dummy data and it's showing fine via:
#recipe = Recipe.find(params[:id])
#comments = #recipe.rcomments
So I tried
#newcomments = #recipe.rcomments.build(params[:recipe])
But it doesn't work at all with an error:
undefined method `rcomments_path' for #<#:0x25ccd10>
How do I get it to display a usable form_for?
%= form_for(#newcomments) do |f| %>
<%= f.label :Comments %>
<%= f.text_field :comment%>
<%= f.label :ratings %>
<%= f.text_field :rating %>
<%= f.submit "Submit Comment", class: "btn btn-large btn-primary" %>
<% end %>
You've created a form for Rcomment creation, but you don't have an rcomments entry in your routes.rb. However, I think what best fits your problem is creating rcomments through a recipe. You can do this with accepts_nested_attributes_for and fields_for.
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
So, something like this--
In your Recipe model, add:
attr_accessible :rcomments_attributes
accepts_nested_attributes_for :rcomments
And in your recipes#show view:
<%= form_for(#recipe) do |f| %>
<% f.fields_for :rcomments do |cf| %>
<%= cf.label "Comments" %>
<%= cf.text_field :comment%>
<%= cf.label "Ratings" %>
<%= cf.text_field :rating %>
<% end %>
<%= f.submit "Submit Comment", class: "btn btn-large btn-primary" %>
<% end %>