For an application I''m writing I have a model object, "Answer", many of which are associated with a "Request" object. A user will need to answer many questions, each of which is stored in an Answer object that is associated with their request (Request has many Answers). Is there an easy way to create and then validate each of these Answer objects? I basically want to do the following: What is the recommended way to generate forms and validate collections of model objects? For example, I have an "Answer" object and users will need to fill out a form of many of these objects. Then the application needs to verify that all text fields are not blank before saving. It sounds simple and I feel that I''m missing something obvious because I can''t figure out a simple way of accomplishing this task. Here''s a more concrete example: ------- app/controllers/request_controller.rb ------- class RequestController < ApplicationController def make_request # session[:resource] has been defined elsewhere.... @answers = session[:resource].prepare_answers end def complete_request answers = Array.new all_good = params[:answers].all? { |a| a = Answer.create!(a) } if all_good redirect_to :action => ''complete_request'' else render :action => ''make_request'' end end end ------- ------- app/views/request/make_request.rhtml ------- <% if flash[:error] %> <div id="error"><%= flash[:error] %></div> <% end %> <%= start_form_tag :action => ''complete_request'' %> <table> <% @answers.each do |answer|%> <tr> <td><%= answer.question_text %></td> <td><%= text_field ''answer[]'', ''text'' %> </td> </tr> <% end %> </table> <%= submit_tag "Submit" %> <%= end_form_tag %> ------- Unfortunately, that simple code does not work. Because all of the Answers in the @answers collection are new objects they do not have associated ids. Without those ids the '' <%= text_field ''answer[]'', ''text'' %> '' line doesn''t work since ''[]'' only works with ids. Now, I could change the loop to append a increasing int to the answer name and then, in the complete_request action, break out the int from the answer_# object returned in params to reassemble the array. That''s seems really clumsy for something that should be simple. I mean, in PHP you can do something like ''<input type="text" name="answer[]">'' and then you''ll get an array of answer objects in the $_POST or $_GET variables even if they don''t have associated ids. Is there some way to get the same thing in Rails? Or, alternatively, am I looking at this problem the wrong way since I''m new to Ruby and Rails and Rails has a better way of getting the same result (get information for and save a collection of new model objects)? -- Ryan
Mark Reginald James
2006-Jan-02 10:20 UTC
[Rails] Re: Dealing with collections of model objects
Ryan Nielsen wrote:> <% @answers.each do |answer|%> > <tr> > <td><%= answer.question_text %></td> > <td><%= text_field ''answer[]'', ''text'' %> </td> > </tr> > <% end %> > > Unfortunately, that simple code does not work. Because all of the > Answers in the @answers collection are new objects they do not have > associated ids. Without those ids the '' <%= text_field ''answer[]'', > ''text'' %> '' line doesn''t work since ''[]'' only works with ids.''[]'' will create an array in params, but for it to work with new objects you''ll have to instead render the text field using something like <%= text_field_tag ''answer_texts[]'' %> If you also want the boxes re-filled after a bad post, you can do something like: <% @answers.each_with_index do |answer, i| %> <tr> <td><%= answer.question_text %></td> <td><%= text_field_tag ''answer_texts[]'', params[:answer_texts] ? params[:answer_texts][i] : nil %></td> </tr> <% end %> -- We develop, watch us RoR, in numbers too big to ignore.