I wrote a form that generates a text input for each property.
The list of properties is configurable by the customer.
<% properties = ["refractivity_at_2kHz", "refractivity_at_5kHz"] %>
<% properties.each do |property| %>
<div class="property">
<%= f.label property %>
<%= f.text_field property %>
</div>
<% end %>
It fails with the error undefined method refractivity_at_2kHz.
What is the usual solution for this problem?
Should I add an array to my model, and use f.text_field myarray[property] ?
Is it a form_for(#model)?
Because then f.text_field(property) looks for that method/property on #model.
May be you want to change f.text_field(property) into text_field_tag(property)[1]
cheers
[1] http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-text_field_tag
Related
I have this code in the (ERB) view file:
<% if current_page?(some_object_path(some_object)) %>
<%= f.submit "Create Some Object", class:'btn btn-success'%>
<% else %>
<%= f.submit "Update Some Object", class:'btn btn-info'%>
<% end %>
and this:
<%= form_tag import_some_object_path, multipart: true do %>
<%= file_field_tag :file, class: "" %>
<%= submit_tag "Import CSV", class: "btn btn-info " %>
<% end %>
Now, the issue is that I have several of these different paths relating to respective classes (tables in the database). I don't want to replicate these codes in all 9 Class views in the app. Is there a way to refactor this so I can reference the code in just one location (say, a _partial), and then rails knows what object to insert in the some_object field depending on say, the current_page? Is there a magic wand way to do this?
(I have really scoured the internet but I can't find a solution. It may be that I am using the wrong search terms though)
Let's say I have a schema in which an apple crate contains zero or more apples. While editing the apple crate in a form, I want to list the apples and provide a checkbox next to each apple, for deleting it when the form is submitted.
There is nothing going wrong that I can see. In my model I say
class AppleCrate < ActiveRecord::Base
has_many :apples
accepts_nested_attributes_for :apples, :allow_destroy => true
...
end
I have the form working, so far as I can tell. The checkboxes appear in the form html and when the form is processed by the controller each apple in the list has an attribute called "_destroy" which is set to either "1" or "0" depending on whether or not I checked the box before submitting.
According to the Rails API, when I set _destroy to 1 and save, the apple should be deleted. But when I submit the form I get
ActiveRecord::UnknownAttributeError in AppleCrateController#update
unknown attribute: _destroy
...
"apple_crate"=>{"id"=>"10101", "apples"=>{"1"=>{"id"=>"1",
"variety"=>"granny smith",
"apple_crate_id"=>"10101",
"_destroy"=>"1"},
"2"=>{"id"=>"2",
"variety"=>"fuji",
"apple_crate_id"=>"10101",
"_destroy"=>"1"},
"3"=>{"id"=>"3",
"variety"=>"macintosh",
"apple_crate_id"=>"10101",
"_destroy"=>"0"},
...
and so on.
I must be missing something obvious but after several days of futzing around I can't figure it out. I can successfully do everything else -- update, edit, index, etc -- so long as I leave out the :_destroy attribute. Any ideas?
(For what it's worth, I'm running rails 3.2.2 on Windows.)
Updated:
This is what I'm looking at in the documentation. (See the subsection "One-to-many".)
Updated:
As requested in comments, here is the view:
<%= form_for #apple_crate do |f| %>
<% #apples = #apple_crate.apples %>
<% #apples.each do |apple| %>
<%= fields_for "apples[]", apple do |apple_fields| %>
<%= apple_fields.text_field :variety %>
<%= apple_fields.hidden_field :apple_crate_id %>
<%= apple_fields.hidden_field :id %>
<%= apple_fields.check_box :_destroy %>
<% end %>
<% end %>
<%= f.submit "Save" %>
<% end %>
You should generate nested forms and forms with rails helpers, don't do it by your hands. So I think that's where your error at.
Try:
<%= form_for #apple_crate do |f| %>
<%= f.fields_for :apples do |apple_fields| %>
<%= apple_fields.text_field :variety %>
<%= apple_fields.hidden_field :apple_crate_id %>
<%= apple_fields.hidden_field :id %>
<%= apple_fields.check_box :_destroy %>
<% end %>
<% end %>
something like this, did not check if it's correct, but idea should be clear enough
I have a simple dropdown that I want to populate from a model. I don't want to bind it to another model at all, just a simple standalone form with a list of items and handle storing the state of the dropdown in a session variable, I can achieve it with a more brute force approach as shown but it doesn't feel very 'rails' to me.
<form action='/home/switch' method='post'>
<select name="all_items">
<% #items.each do |i| %>
<option value="<%= i.id %>" <%= i.id.to_s == session[:current_item] ? "selected" : "" %>><%= i.name %></option>
<% end %>
</select>
<input type="submit">
</form>
Is there a better way to do this in Rails?
Update: Yep. collection_select worked for me:
<%= collection_select(:item, :id, Item.all, :id, :name, {:selected => session[:current_item].id}) %>
Take a look at form_tag, select_tag, options_from_collection_for_select, and/or collection_select.
So your example might look like this (not tested, may have typos)
<%= form_tag('/home/switch') do %>
<%= select_tag('all_items', options_from_collection_for_select(#items, 'id', 'name')) %>
<%= submit_tag %>
<%= end %>
This is missing the "selected" bit, take a look at the docs for that.
form with the single submit. How to store that values in the data base
<%= form_for (#movie) do |f| %>
//Movie
<%= f.label :moviename,"Movie Name:"%>
<%= f.text_field :moviename%>
//Releases
<%= f.fields_for :release do |release_fields| %>
<%= release_fields.label :theatre,"Theatre :"%>
<%= release_fields.text_field:theatre%>
<%= release_fields.label :city,"City :"%>
<%= release_fields.text_field:city%>
<%= release_fields.label :releasedate,"Release Date :"%>
<%= release_fields.text_field:releasedate%>
//Submit:
<%= f.submit "Save The Movie"%>
<% end %>
<% end %>
this is the form with the single submit button.There an error it showing the unknown attribute release can any on help with is issue Please
fields_for is expecting to access #movie.release, does that exist?
I'm editing multiple instances of a parent model in an index view in one form, as in Railscasts #198.
Each parent has_many :children and accepts_nested_attributes_for :children, as in Railscasts #196 and #197
<%= form_tag %>
<% for parent in #parents %>
<%= fields_for "parents[]", parent do |f|
<%= f.text_field :job %>
<%= f.fields_for :children do |cf| %>
<% cf.text_field :chore %>
<% end %>
<% end %>
<% end %>
<% end %>
Given parent.id==1
f.text_field :job correctly generates
<input id="parents_1_job" type="text" value="coding" size="30" name="parents[1][job]">
But cf.text_field :chore generates ids and names that don't have the parent index.
id="parents_children_attributes_0_chore"
name="parents[children_attributes][0][chore]"
If I try passing the specific child object to f.fields_for like this:
<% for child in parent.children %>
<%= f.fields_for :children, child do |cf| %>
<%= cf.text_field :chore %>
<% end %>
<% end %>
I get the same. If I change the method from :children to "[]children" I get
id="parents_1___children_chore"
which gets the right parent_index but doesn't provide an array slot for the child index.
"[]children[]" isn't right either:
id="parents_1__children_3_chore"
as I was expecting attributes_0_chore instead of 3_chore.
Do I need to directly modify an attribute of the FormBuilder object, or subclass FormBuilder to make this work, or is there a syntax that fits this situation?
Thanks for any thoughts.
I did solve this problem by reading the source code for FormBuilder.fields_for
One possible answer: Yes, modify the f.object_name attribute of the FormBuilder object.
Specifically in this situation
f.fields_for :children
is going to call
f.fields_for_with_nested_attributes
which sets the name variable based on f.object_name. The id for the generated element looks like it is based on the name,so both match in the resulting html.
def fields_for_with_nested_attributes(association_name, args, block)
name = "#{object_name}[#{association_name}_attributes]"
.....
So one way to tell f.fields_for to do what I wanted is to set f.object_name to include the parent id for the duration of the f.fields_for block
<% old_object_name = f.object_name %>
<% f.object_name="parents[#{f.object.id}]" %>
<% =f.fields_for :children do |cf| %>
<%= cf.text_field :chore %>
<% end %>
<% f.object_name=old_object_name #should be "parents[]" %>
Then everything within the f.fields_for block can use the standard rails helpers unmodified.