I'm attempting to edit a model's nested attributes, much as outline here, replicated here:
<%= form_for #person do |person_form| %>
<%= person_form.text_field :name %>
<% for address in #person.addresses %>
<%= person_form.fields_for address, :index => address do |address_form|%>
<%= address_form.text_field :city %>
<% end %>
<% end %>
<% end %>
In my code, I have the following:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<% for subitem in #meal.meal_line_items %>
<!-- # Edit 2: I need to display information here about the subitem
Which I can't find a way to pass it to the partial, or work in
this manner for existing items
-->
<%= subitem.food.name %>
<%= subitem.food.calories %>
<%= f.fields_for subitem, :index => subitem do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
This works great, except, when I look at the HTML, it's creating the inputs that look like the following, failing to input the correct id and instead placing the memory representation(?) of the model. As a result, an update fails:
<input type="text" value="2" size="30" name="meal[meal_line_item][#<MealLineItem:0x00000005c5d618>][servings]" id="meal_meal_line_item_#<MealLineItem:0x00000005c5d618>_servings">
EDIT:
The reason I'm attempting to do it in this method is that I need to gather some information on associations for existing meal_line_items. For example, in the area where I took out code, I have some code to the effect of:
<%= subitem.food.name %>
<%= subitem.food.calories %>
Getting this information won't work if I am using a form builder with partials, at least, not in my trials.
Edit 2:*
See the edit in the code. Here's my MealLineItem
class MealLineItem < ActiveRecord::Base
# Associations ---------------------
belongs_to :food
belongs_to :meal
end
And meal accepts_nested_attributes for the model. As you can see it belongs to both food and meal model. For the existing meal_line_item I need to do something like:
meal_line_item.food.name
Is there f. missing from <%= fields_for?
--edit
Have you tried:
<%= f.fields_for 'meal[meal_line_item][]', subitem do |line_item_form| %>
--edit
Docs say that it should work without loop too:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<%= f.fields_for :meal_line_items do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<%= f.submit %>
<% end %>
Have to test this but maybe this approach?
_form
<%= form.fields_for :meal_line_items do |meal_line_item_form| %>
<% #meal.meal_line_items.each do |meal_line_item| %>
<%= render :partial => "meal_line_items/meal_line_item", :locals => { :meal_line_item_form => meal_line_item_form, :meal_line_item => meal_line_item } %>
<% end %>
<% end %>
meal_line_items/_meal_line_item.erb
<%= meal_line_item_form.label :servings %><br/>
<%= meal_line_item_form.text_field :servings %><br/>
<%= meal_line_item_form.label :food_id %><br/>
<%= meal_line_item_form.text_field :food_id %><br/>
EDIT
here's a link to an example for setting the formbuilder iterator directly (Rails 2.3.8 though). The associations between Outbreak -> Incidents -> Location should be similiar to the ones for Meal -> Meal_line_items -> Food.
AJAX update of accepts_nested_attributes_for partials
After searching high and low, I found the error. Although I was modifying the partial and was receiving a NameError it's because I was calling the partial from a helper method - exactly the same problem as stated in the following question:
rails fields_for render partial with multiple locals producing undefined variable
Related
I am trying to add dynamic fields to my rails application.
I have a fields_for
<%= form.fields_for :books do |book| %>
<%= render 'book_fields', form: book %>
<% end %>
<%= link_to_add_fields "Add Field", form, :books %>
When it renders book_fields I am getting the following error
If I am passing form in render why would I be getting this error?
I have tried book.label :title but I get the same error but instead of the undefined varaible being form it is book. Any ideas? Thanks in advance.
UPDATE:
<%= form.fields_for :books do |builder| %>
<%= form.label :title %>
<%= form.text_field :title %>
<%= form.hidden_field :_destroy %>
<% end %>
If I remove the partial render and stick the form text fields and labels into the fields_for itself it works. While rendering the partial, that is when I get the error.
Instead using the form block variable as the local in your render method, you have to use the builder one, like:
<%= form.fields_for :books do |book| %>
<%= render 'book_fields', f: book %>
<% end %>
In the partial:
<fieldset>
<%= f.label :title %>
</fieldset>
The error is happening because you're using your "main" form variable, and when the partial is being load, Rails try to find it as a local variable, which doesn't exist in that context.
Let's say I have a cat model and a life model. And let's say a cat (#cat) has_many lives, and a cat accepts_nested_attributes for a life.
Now, if I wanted to update 7 lives (#lives) at once, using one form_for(#cat), how would that form look like? This is what I've tried, but in this form only the attributes for the last life are passed to the params hash:
<%= form_for(#cat) do |f| %>
<% #lives.each do |life| %>
<%= f.fields_for(life) do |l| %>
<%= l.input :date_of_birth, as: :date %>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
You need to build the attributes in your controller
#cat = Cat.find(<criteria>)
#cat.lives.build
In your example, you have a loop inside a loop. Try this:
<%= form_for(#cat) do |f| %>
<%= f.fields_for(:lives) do |l| %>
<%= l.input :date_of_birth, as: :date %>
<% end %>
<%= f.submit %>
<% end %>
I am creating a survey with the following data model:MathTest has_many math_questions
On MathTest#update I want to create one form for every question. The form should look something like this:
<%= form_for(mathtest) do %>
<% math_question.each do |question| %>
<%= f.label :answer %>
<%= f.text_field :answer %>
<%= f.hidden_field math_question.id %>
<% end %>
<% f.submit %>
<% end %>
I want to send the MathTest Controller a set of tuples with a math_question id and the answer for that question. Then in the Controller, I can call another method that evaluates each question's answer.
How do I write my form to send the appropriate tuple?
This should do it:
<%= form_for(mathtest) do |f| %>
<% math_question.each do |question| %>
<%= f.fields_for :answer do |ff| %>
<%= ff.label :answer %>
<%= ff.text_field :answer %>
<% end %>
<% end %>
<% f.submit %>
<% end %>
Also edit the model:
class MathTest < ActiveRecord::Base
has_many :math_questions
accepts_nested_attributes_for :math_questions
fields_for documentation: http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
I would like to loop through data in my database inside my form. What I would like to do with the data is put it in labels and textboxes. How could I do this in rails? Would I just use a .each block to loop through it inside the form? The reason I have it in my database is because my client would like to be able to add the form field data himself.
For example here is something I would like to do:
<%= form_for :order do |f| %>
#fields.each do |field|
<%= f.label field.name %>
<%= f.text_field field.name %>
<% end %>
<%= f.submit %>
<% end %>
What the best way to accomplish something like this?
Please don't answer with a railscast :)
Thanks in advance
Yes, that will work, though you missed an end script tag on line two:
<%= form_for :order do |f| %>
<% #fields.each do |field| %>
<%= f.label field.name %>
<%= f.text_field field.name %>
<% end %>
<%= f.submit %>
<% end %>
If you need something more complex than just a label/text field pair - then you can use a partial-template and use the collection keyword:
<!-- in 'order.html.erb' -->
<%= form_for :order do |f| %>
<!-- note: each 'field' is auto-populated from the collection/partial-name, but you need to pass the form in as a local -->
<%= render :partial => 'field', :collection => #fields, :locals => {:f => f} %>
<%= f.submit %>
<% end %>
and
<!-- in '_field.html.erb' -->
<%= f.label field.name %>
<%= f.text_field field.name %>
<!-- and whatever else you want to do... -->
more on partial rendering here: http://api.rubyonrails.org/classes/ActionView/Partials.html
My example form
<% form_for #ad do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :ad_type_id %><br />
<%= f.collection_select(:ad_type_id, AdType.all, :id, :name) %>
</p>
<p>
<% #ad.ad_properties.each do |property| %>
<%= property.name %>:
<% f.fields_for :ad_values do |value_field| %>
<%= value_field.text_field :ad_id, :value => #ad.id %>
<%= value_field.text_field :ad_property_id, :value => property.id %>
<%= value_field.text_field :value %>
<% end %><br /><br />
<% end %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p><%= f.submit %></p>
<% end %>
Explanation:
Ad has many properties. I can add new properties at any time (it's a normal model).
Lets say the Ad is of the type 'hotel'. Then I would add properties like 'stars' and 'breakfast_included'
Then I store each of these properties' values in a separate model.
And all this works fine with my form above.
My problem:
These fields are not validated because I can't know what their names are.
I need to add validations dynamically somehow.
My thought:
#Before the normal validations kick in
def add_validations
self.properties.each do |property|
property.add_validation :whatever #somehow :)
end
end
How could I do this?
Have you tried with polymorphic associations ? That's maybe a cleaner approach.
http://railscasts.com/episodes/154-polymorphic-association
Disclaimer: I've never done this before, so I'm not 100% sure it will work.
But as long as you can get the type of the object you are working with, you can use the Rails constantize method to get the model it references (I'm assuming that if ad can be of type Hotel, then you have a Hotel model). At that point you should probably have the appropriate validations on your Hotel model.