Rails 3 Edit Multiple Records in a Single Form - forms

I've been stuck on this problem for a couple of days now.
I've have some success with Railscasts Episode #198, but that one is for Rails 2. There have been some changes in Rails 3 that make it so the code provided in Episode #198 won't work.
The problem lies within the edit_individual.html.erb:
Original Code (provided by Ryan # Railscasts):
<% form_tag update_individual_products_path, :method => :put do %>
<% for product in #products %>
<% fields_for "products[]", product do |f| %>
<h2><%=h product.name %></h2>
<%= render "fields", :f => f %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
Modified Code (simply changed fields_for to form_for):
<% form_tag update_individual_products_path, :method => :put do %>
<% for product in #products %>
<% form_for "products[]", product do |f| %>
<h2><%=h product.name %></h2>
<%= render "fields", :f => f %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
In the new code, each record is placed within a form of their own, all inside one single form (which is the one I only want).
My question is, how can I get the code provided by Railscasts Episode #198 to work in Rails 3?
Here is a link to the Railscast I mentioned:
http://railscasts.com/episodes/198-edit-multiple-individually
Thank You,
c.allen.rosario

I found the solution. Just need to modify the following line in the code provided by Ryan # Railscasts:
<% fields_for "products[]", product do |f| %>
and change it to:
<%= fields_for "products[]", product do |f| %>
Notice, that the <% has been modified to <%=.
final solution:
<% form_tag update_individual_products_path :method => :put do %>
<% for product in #products %>
<%= fields_for "products[]", product do |f| %>
<h2><%= h product.name %></h2>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
I was wondering if anyone could explain this solution to me. From what I understand you should only need a <% in front of the fields_for.
c.allen.rosario

The change in Rails 3 from <% fields_for to <%= fields_for is because it was confusing that form_for, form_tag, etc... were using <% form... %> even though they they were outputting html code.
With Rails 3, since they output html code, they use <%=.
Please note that your first line is deprecated:
<% form_tag update_individual_products_path, :method => :put do %>
should be
<%= form_tag update_individual_products_path, :method => :put do %>
Same for all form tags.

Related

How to DRY two slightly different forms?

I know about partial in rails, but it seems that I can only re-use exactly the same form with partial.
What if I have two forms that differ only in one field? For example, in my classroom app, I have one form for a peer-grader and one form for a teacher-grader.
The teacher's form is as follows. The peer-grader form is exactly the same, minus the grade field. How do I DRY this?
<%= form_for #doc,
url: student_homework_document_path(student_id: #doc.submitter_id,
id: #doc.id),
html: { multipart: true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :grade %>
<%= f.number_field :grade %>
<%= f.label :graded_file %>
<%= f.file_field :graded_file %>
<%= f.label :graded_file_source_code %>
<%= f.file_field :graded_file_source_code %>
<%= f.submit "Submit grading", class: "btn btn-large" %>
<% end %>
I would have thought you had one controller called teachers and one called peers or something. You could keep the form the same but add a variable to the peer-grader method such as #peer_grader = true. Then in your form add:
<% if #peer_grader = true %>
<%= f.label :grade %>
<%= f.number_field :grade %>
<% end %>
You would also need to set another variable called #url in both controllers set to the correct path and then update the form to:
<%= form_for #doc, url: #url, html: { multipart: true } do |f| %>

I have created a netsted form and action, but keep getting a to_key error

I'm trying to follow along with a tutorial. I am using the same methods as a Blog Post and Blog Comment type tutorial, just trying something a little different. I keep getting an error:
undefined method `to_key' for #(had to remove the first <)Agentinteraction::ActiveRecord_Relation:0x007fa4d43ca138>
With the errors highlighted as: NoMethodError in Agents#show
<% form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
Routes:
resources :agents do
collection do
post 'create_qrreview', to: 'agents#create_qrreview'
end
end
Agents Show Action:
def show
#qrreviews = Agentinteraction.where("agent_id = ?", #agent.id)
#agentinteraction = Agentinteraction.new
end
show.html.erb
<p id="notice"><%= notice %></p>
<%= #agent.name %>
<%= #agent.email %>
<%= #agent.team %>
<%= link_to 'Edit', edit_agent_path(#agent) %> |
<%= link_to 'Back', agents_path %>
QR Feedback:<br/><br/>
<%#= #comments.blog %>
<% #qrreviews.each do |qrreview| %>
<%= qrreview.agent_id %><br>
<%= qrreview.yes_or_no %><br>
<% end %>
<br/><br/>
<% form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
Category:
Interaction:
Act One Score:
Act Two Score:
Act Three Score:
Type of Interaction:
Training Needed?
Type of Training Needed?
<%= f.submit %>
<% end %>
undefined method `to_key' for Agentinteraction::ActiveRecord_Relation:0x007fa4d43ca138
The problem is you have define #qrreviews = Agentinteraction.where("agent_id = ?", #agent.id) which returns a AR_Relation.
Try changing
#qrreviews = Agentinteraction.where("agent_id = ?", #agent.id)
to
#qrreviews = Agentinteraction.where("agent_id = ?", #agent.id).first
Also
<% form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
should be
<%= form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>

Variants of <% when writing code inside views in MVC2

I'm currently learning MVC2, and I have seen three variants of the tags that contain the actual code for a View:
<% ... %>
With a = after the %
<%= ... %>
and with a : after the %
<%: ... %>
What is the difference of these three code containers?
And are there any other variants of these?
<% ... %>
is just a block of code
<%: "blah blah" %>
Is Shorthand for
<%= Html.Encode("blah blah") %>
Which is shorthand for
<% Response.Write(Html.Encode("blah blah")) %>
1.<% ... %> just block of code
<%if (Model.HelloWorld != null){%>
Hello World!!
<%} %>
2.<%= ... %> plain text without escaping
<%=Model.HelloWorld %>
3.<%: ... %> text with escaping equal <%= Server.HtmlEncode(Model.Something) %> Details here
<%:Model.HelloWorld %>

Rails 3 fields_for different layout for existing records/new records, file uploads

I have a Content model which has one or many Audio files which need to be added by the new/edit form.
What I have did is created the models with this relationship:
class Audio < ActiveRecord::Base
belongs_to :content
has_attached_file :audiofile,
end
class Content < ActiveRecord::Base
...
has_many :audios
accepts_nested_attributes_for :audios, :allow_destroy => true
end
Now in my new Content form I have the following:
<% f.fields_for :audios do |audiof| -%>
<%= f.label :audiofile, 'Audio file:' %>
<%= audiof.file_field :audiofile %>
<% end -%>
What I need it to do is show me the file_field only for a new Audio file and for the existing ones just print me a file size,name and probably a delete button.
I have also created a new record in the controller with:
#content.audios.build
I am using Rails 3.0.3 with Paperclip plugin for upload. Sorry if the question is too nooby.
Thanks.
From my memory, you will be able to access to the instance of the object within the fields_for statement.
Try something like that :
<% f.fields_for :audios do |audiof| -%>
<% if audiof.object.new_record? %>
<%= f.label :audiofile, 'Audio file:' %>
<%= audiof.file_field :audiofile %>
<% else %>
<%= "Filename = #{audiof.object.audiofile.filename}" %>
<%= "url = #{audiof.object.audiofile.url}" %>
<% end %>
<% end -%>
If audiof.object returns nil(In that case, it is not the good name), check by displaying all the public methods <% = raise audiof.public_methods.inspect %>
The object method should return an instance of an Audio class.

rails 3 form_for doesn't output anything

Hi I have any form with nested form, for example
<% form_for :main do |f| %>
trying to insert code here
<% fields_for :nested do |nested_form| %>
<%= nested_form.text_field :description %>
<% end %>
<% end %>
And then I am trying to insert anything to a main form, nested form doesn't produce any output. It outputs only when it is the only object in main form. Any suggestions?
From the Rails 3 documentation examples you need to write your form_for like this:
<%= form_for :main do |f| %>
# trying to insert code here
<%= fields_for :nested do |nested_form| %>
<%= nested_form.text_field :description %>
<% end %>
<% end %>
Note the <%= for both form_for and fields_for