Dealing with collections of model objects


#1

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] %>

<%= flash[:error] %>

<% end %>
<%= start_form_tag :action => ‘complete_request’ %> <% @answers.each do |answer|%> <% end %>
<%= answer.question_text %> <%= text_field 'answer[]', 'text' %>
<%= 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 ‘’ 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


#2

Ryan N. wrote:

‘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| %>

<%= answer.question_text %> <%= text_field_tag 'answer_texts[]', params[:answer_texts] ? params[:answer_texts][i] : nil %> <% end %>


We develop, watch us RoR, in numbers too big to ignore.