[Beginner] fields_for within each loop

Hello Please help me to find this code work.

I'm trying to make a report with predefined questions. I have made questions from the scaffold and filled it. Now is to assign answer fields per each questions.

[DATA TYPE] class Report < ActiveRecord::Base   has_many :answer_singles end

class AnswerSingle < ActiveRecord::Base   belongs_to :report end

reports/_form.html.erb   <div class="question">     <% QuestionSingle.all.each_with_index do |question, index| %>       <p><%= index+1 %>. <%= question.content %></p>       <p>         <%= f.fields_for :answer_singles do |answer| %>           <%= answer.text_area :content %>         <% end %>       </p>     <% end %>   </div>

it shows well but once submit it makes error 1. Question 1 [text area] 2. Question 2 [text area]

[error when submit] AnswerSingle(#18194030) expected, got Array(#1133380)

I think the reason is using :answer_singles for fields for. Is there any better code to implement this?

Thank you and regards, June

By making it nested_attributes I'm able to control it but still some weird loop. I don't fully understand how loop works in rails so please advise.

First this code makes one text area per each question.   <div class="question">     <% QuestionSingle.all.each_with_index do |question, index| %>       <p><%= index+1 %>. <%= question.content %></p>         <%= f.fields_for :answer_singles, {:question_id => :index} do

answer> %>

          <%= answer.text_area :content %>         <% end %>     <% end %>   </div>

After I put answers and edit it makes number of answer text area same as questions.

Please let me know how I can make the text area per question.

Thank you and regards, June

I think helping you would be easier when knowing the code of the action that processes the form input. Could you please provide that too?

Sure, Thank you very much.

reports_controller.rb def new     @report = Report.new     @report.answer_singles.build

    respond_to do |format|       format.html # new.html.erb       format.json { render :json => @report }     end   end

_form.html.erb <%= form_for(@report) do |f| %>   <% if @report.errors.any? %>     <div id="error_explanation">       <h2><%= pluralize(@report.errors.count, "error") %> prohibited this report from being saved:</h2>

      <ul>       <% @report.errors.full_messages.each do |msg| %>         <li><%= msg %></li>       <% end %>       </ul>     </div>   <% end %>

  <div class="field">     <%= f.label :project_id, "Project Runner" %><br />     <%= f.select :project_id, Project.all.collect {|d| [Project::P_PARTNER[d.partner], d.partner]} %>   </div>   <div class="field">     <%= f.label :finalized %><br />     <%= f.select :finalized, [["Yes", true], ["No", false]] %>   </div>

  <div class="field">     <%= f.label :emails %><br />     <%= f.number_field :emails %>   </div>

  <div class="question">     <% QuestionSingle.all.each_with_index do |question, index| %>       <p><%= index+1 %>. <%= question.content %></p>         <%= f.fields_for :answer_singles, {:question_single_id => :index} do |answer| %>           <%= answer.text_area :content, {:question_single_id => :index} %>         <% end %>     <% end %>   </div>

  <div class="actions">     <%= f.submit %>   </div> <% end %>

Others are just as the scaffold output (index, edit, new, show)

I found from the development log that I'm passing question_single_id as nil. Seems to be my code of this part is not working

<%= f.fields_for :answer_singles, {:question_single_id => index} do

answer> %>

    <%= answer.text_area :content, {:question_single_id => index} %>

What I meat to do was to assign question_single_id when I fill the answer :content. And look up a text_area per each question.

Is there any good solution for text_area and fields_for usage?

I know I'm way far from CRUD development but what to do. (codes are getting uglier)

What i should implement is like a quiz system with given questions. User login -> answer the given questions -> end Admin -> edit questions or review user answers -> end

So, with nested_attributes, you're not supposed to iterate over anything at all - f.fields_for :answer_singles will iterate over all the report's AnswerSingle object and yield to the block once for each one. With this way of thinking if you want one AnswerSingle for each QuestionSingle then you'd want to do something like this in your controller

QuestionSingle.each do |qs|   report.answer_singles.build ... end

passing to build whatever attributes need to be set on the answer_single to link it to the question single it corresponds to.

Fred

Thank you very much Frederick.

I have changed my code according to it. But in the form how I can implement this? Once I'm using the same code it will display 3 fields since it's using fields_for loop for all answers.

What can I use in this case?

Thank you very much Frederick.

I have changed my code according to it. But in the form how I can implement this? Once I'm using the same code it will display 3 fields since it's using fields_for loop for all answers.

just <%= field_for :answer_singles do |f| %> ... <% end %>

will iterate over all of report.answer_singles and execute the block (e.g. to display a heading & a text area). rails takes cate of generating different names for form elements so that it doesn't get all mashed together. Since these are all unsaved elements, you'd probably want a hidden input to track the question id for the question corresponding to the text area you are showing.

Fred

It doesn't work as I expected. I changed the controller and view but it doesn't work

in report_controller.rb

def new ...

  QuestionSingle.each do |qs|     report.answer_singles.build ...   end

so answer_single generated as many as questions.

So when I call answer_singles in the fields for it calls every answer_singles generated.

<div class="question">     <% QuestionSingle.all.each_with_index do |question, index| %>       <p><%= index+1 %>. <%= question.content %></p>         <%= f.fields_for :answer_singles do |answer| %>           <%= answer.text_area :content %>           <%= answer.hidden_field :question_single_id, {:value => index} %>         <% end %>     <% end %>   </div>

I have designed models not like report -> question -> answer report -> answer (due to the predefined questions by scaffolding)

For all report same questions will be fed and answers have report_id, question_id. My question is how I can use answer same as the question_id.

Simple fields for shows all answer fields having same report_id.

Let me know if there's better design for predefined questions.

Thanks, June

def new ...

QuestionSingle.each do |qs| report.answer_singles.build ... end

so answer_single generated as many as questions.

So when I call answer_singles in the fields for it calls every answer_singles generated.

<div class="question"> <% QuestionSingle.all.each_with_index do |question, index| %> <p><%= index+1 %>. <%= question.content %></p> <%= f.fields_for :answer_singles do |answer| %> <%= answer.text_area :content %> <%= answer.hidden_field :question_single_id, {:value => index} %> <% end %> <% end %> </div>

So it's entirely normal that fields_for :answer_singles iterates over all of them - that's how nested attributes work. If i were you i would ditch the iteration over QuestionSingle and leave the iteration stuff to fields_for - when displaying a given answer single I assume that you're able to locate the corresponding question to display it's content.

Fred

Thank you Fred for another reply.

But having relationship report->question->answer will lead to unnecessary generation of the question per each report. In my case, question is same for all reports.

Could you please guide me what I should do then? I feel like I'm stuck in db model now.

Your advise will be very much appreciated.