Re: Creating Variable Number of Models in One Form

Hi guys!

At first, thanks a lot for this great tutorial, Ryan. You've saved hours of my life..

There is just one question left: I don't like bothering the server with this stuff and can't always ensure that my user's browser supports Ajax, so are there any ideas on how to achieve the same thing without it?
I thought about just setting a global JS variable which stores the current index, but is there any chance to still use RJS then? Putting the raw JS to add the partial somewhere isn't too nice and truly a mess to maintain.


Thank you!

Pascal

Re: Creating Variable Number of Models in One Form

you are awesome

i am totally going to be looking at this article a ton while i try to make something fairly similar :-)

Re: Creating Variable Number of Models in One Form

This has been extremely helpful for me as well.

I'm running into a problem with validating an associated model, however. I have a Photo model (based on attachment_fu) that belongs to a ResourceItem model. In my view for creating a new resource_item, users can add or remove photos and then click "create." This works great if they have uploaded a photo or if they have removed all photo fields.

If they leave a blank photo field, however, there will be a validation failure. ResourceItem will try to validate associated photos; the associated photos will be blank and therefore won't validate_as_attachment.

What I'd like to do is check to see if the photo file_field is blank for each photo. If it is, I'd like to remove it from my @resource_item object. Only then will I save the resource_item. I'm not sure how to do this -- or if this is even the best way to go. Any suggestions would be great!

Below is the pertinent code:

# Photo.rb includes 
belongs_to :resource_item
validates_as_attachment

# ResourceItem.rb includes
class ResourceItem < ActiveRecord::Base
  has_many :photos, :dependent => :delete_all
  after_update :save_photos           
  validates_associated :photos

# resource_items_controller.rb
  def new
    @resource_item = ResourceItem.new
    2.times { @resource_item.photos.build }
  end

  def create
    @resource_item = ResourceItem.new(params[:resource_item])
   
    # put some code in here that would remove photos if user hasn't uploaded anything -- so that validation doesn't fail
   
    if @resource_item.save
      flash[:notice] = "You have successfully created a resource!"
      respond_to do |wants|
        wants.html { redirect_to resource_items_url }
        wants.xml  { render :xml => @resource_item.to_xml }
      end
    else
      render :action => 'new'
    end     
  end

# from _add_photo.html.erb:
<div class="add_photo">
    <% fields_for "resource_item[photo_attributes][]", add_photo do |photo_form| %>
            Photo 1:<%= photo_form.file_field 'uploaded_data', :index => nil %><br />
            caption: <%= photo_form.text_field :caption, :index => nil %><br />
            <% if add_photo.new_record? %>
                <%= link_to_function "remove", "$(this).up('.add_photo').remove()" %>
            <% else %>
                <%= link_to_function "remove", "mark_for_destroy(this)" %>
                <%= photo_form.hidden_field :id, :index => nil %>
                <%= photo_form.hidden_field :should_destroy, :index => nil, :class => 'should_destroy' %>
            <% end %>
<% end %>
</div>

Re: Creating Variable Number of Models in One Form

Hi there!

I've followed the tutorial at Railscasts.com and the one in Advanced Rails Recipes (that doesn't worked, so now I have a hybrid solution) and all works fine except when I try to use a checkbox in the child model partial. When I do this, the parameters hash are broken, like this:

Parameters hash without the checkbox (or when unchecked):

{"commit"=>"Update",
"_method"=>"put",
(...),
"existing_time_entry_attributes"=>
  [{"task_id"=>"1",
"description"=>"new description",
"temporary"=>"0",
"id"=>"22",
"should_destroy"=>""},
{"task_id"=>"1",
  "description"=>"tests",
  "temporary"=>"0",
  "id"=>"23",
  "should_destroy"=>""}],

"worker_id"=>"1"}}


Now with the checkbox checked (the attribute is called "temporary", a boolean):

{"commit"=>"Update",
"_method"=>"put",
(...),
"existing_time_entry_attributes"=>
  [{,
"task_id"=>"1",
"description"=>"pix 2.0",
"temporary"=>"1"},
{"should_destroy"=>"",
"task_id"=>"1",
"id"=>"22",
"temporary"=>"0",
"description"=>"tests"},
{"should_destroy"=>"",
"id"=>"23",
"temporary"=>"0"}],

"worker_id"=>"1"}}


As you can see, I have two registers and try to update the first one by checking the checkbox. The "existing_time_entry_attributes" array should have two positions, but is passed with three. the "brake" is right there on the boolean attribute. Anyone knows a solution?

Re: Creating Variable Number of Models in One Form

First off, thanks for a fantastic tutorial. I can't believe I blew an hour trying to figure out a problem with the controller.

Using Rails 2.0. When adding another "task", nothing happened and I kept getting the following in development.log:
ActionController::MissingTemplate (Missing template people/add_address.html.erb in view path /home/Scott/track/app/views):

Turns out I didn't notice I need a respond_to in the controller for add_task

# in projects_controller.rb
def add_task
  @task = Task.new
 
  respond_to do |format|
    format.js
  end 
end

Hope this helps someone.

Re: Creating Variable Number of Models in One Form

Working from this basic scenario, how would I go about adding a nested fields_for element?

I have a form which edits many instances of a "lesson" model and (hopefully) will add any number of "assignments" to any lesson.

<% form_remote_tag :url => {:action => 'update_assignments', :student => @student, :week => @set_week} do |f| %>


<% for lesson in lessons_day_subject %>
  <% fields_for "lessons[#{lesson.id}]", lesson do |f| %>
  ...lesson fields here...   
  <% lesson.assignments.each_with_index do |assignment, index| %>
    <%= render :partial => 'assignment_fields', :locals => { :assignment => assignment, :index => index, :subject => @subject.id, :lesson => lesson } %>
    <% end %>
                   
<%= submit_tag 'Save All' %>
<% end %>

#assignment_fields partial...
#this is what I don't get!
<% fields_for "assignments[#{index}]" do |assignment| %>
  ...assignment fields here...
<% end %>


I'm thinking there should be a way to get things arranged in a nested hash back to the controller, something like...
"
"lessons"=>{"172"=>{"comments"=>"comments here", "assignments"=> {"0"=> {"lesson_id" => "213", "segment_id"=>"78"}, {"1" => {"lesson_id"=>"214", "segment_id"=>"79"}}}...

...but to no avail so far.

Your help is appreciated.

Re: Creating Variable Number of Models in One Form

OK, so I've got a nice nested hash using this string for the fields_for first parameter...

 <% fields_for "lessons_edited[#{lesson}][assignments][#{index}]", assignment do |assignment_form| %>

...stuff here...
<% end %>


That gives me the hash organization that I need.

Now my problem...

The assignment form consists of dynamic drop-downs updated with observe_field. So, the final partial which is used to select the 'segment_id' for the assignment isn't working as I would expect/hope. The 'assignment_form' method from the form builder block doesn't seem to like my select control... neither collection_select nor select. When I use...

 assignment_form.text_field :segment_id

I can manually type in a value and get back the hash I need.

When I use...

 assignment_form.select :segment_id, @segments.collect {|s| [s.id, s.full_name]}

I get...
ActionView::TemplateError (wrong number of arguments (3 for 0)) on line #3 of app/views/lessons/_segments.rhtml:
...
3: <%= assignment_form.select :segment_id, @segments.collect {|s| [s.id, s.full_name]}, {} %>

When I use...
assignment_form.collection_select :segment_id, @segments, :id, :full_name

I get...
ActionView::TemplateError (undefined method `collection_select' for "#<ActionView::Helpers::FormBuilder:0x3461d80>":String) on line #3 of app/views/lessons/_segments.rhtml:
...
3: <%= assignment_form.collection_select :segment_id, @segments, :id, :full_name %>

Any help would be appreciated.

Re: Creating Variable Number of Models in One Form

Hello Ryan, once again thanks for your great work.
I have a form where users can create a project and add several tasks following your railscast (complex forms part 1 and 2) and it works great but I need to know in the task form partial how many tasks are already created so I started looking on internet and in this forum and I found this tutorial that I guess works great but it uses a different approach so my question is: is it possible to add the add_task link the "index" with the code you show on the railscast instead in this tutorial ?

THANK YOU SO MUCH, I APPRECIATE YOUR HELP

Last edited by macsig (2008-03-10 21:04:19)

Re: Creating Variable Number of Models in One Form

hi i'm really a newbie in rails.
i'm doing a project about online rostering.
if i have 2 tables (model) - person, work_shift
is this "Creating Variable Number of Models in One Form" method can be use to make this type of interface (see below):

#it will loop n person i have in table person.
#day will be entered manually using drop down/text field.

Person | shift_day
john   | monday
doe    | tuesday
dann   | wednesday
rob    | thursday
carl   | friday

(save shift)

i want to know if i click (save shift) it will save that 5 new records in shift table.

by the way,
this is what in the table person: id, name
this is what in the table work_shift: person_id, shift_day

i tried this tutorial before in my other project. in 1 form, it will add 2 records. 1 record in user table and 1 record in student table. (work like a charm, thank you!)
e.g.
user - id = 1, name = john
student - id = 1, user_id = 1

130

Re: Creating Variable Number of Models in One Form

Thanks for a really good tutorial.

I have a small problem:
My "tasks" is added fine and it looks nice. But I want to use a in_place_editor_field inside my fields_for for every "task" but I get the error:

"ActionView::TemplateError (undefined method `in_place_editor_for' for #<ActionView::Helpers::FormBuilder:0x244620c>)"


Can I patch the ActionViewHelper in some way or is there a workaround or an other way?

131

Re: Creating Variable Number of Models in One Form

haze: If you're using Rails 2.0, I don't think that the inplace editor is in the core anymore. I believe it's been moved into a plugin.

Re: Creating Variable Number of Models in One Form

Hi Ryan,

Thanks for your tutorial(looks that made it to Advanced Rails Recipe ). I had a look at it and it's much more simpler than the original post.

Re: Creating Variable Number of Models in One Form

Hey All,

I am running into a strange problem where every time I edit two models in one form, and hit the Update button, I get the error :
No route matches "/obligation/update" with {:method=>:post}

I have 2 models : obligation and assignment.

obligation has_many :assignments and assignment belongs_to :obligation

I have changed the update def code and modified the edit file but dont know why it is not working out.

Please help me out with it!

134

Re: Creating Variable Number of Models in One Form

This great article helped me a lot. What is the best way to show error messages for different tasks in case that validation fails? Obviously, <%= error_messages_for "tasks[#{index}]" %> isn't the correct way to handle the situation.

Last edited by jukka (2008-07-13 16:41:35)

Re: Creating Variable Number of Models in One Form

Hi Ryan,

Just wanted to extend a huge thank you. I'm just beginning with rails and this tutorials you've made about forms were just what I needed. Again, Thank You!

136

Re: Creating Variable Number of Models in One Form

Yeah, if you need to reference it I would do it by hand.

Re: Creating Variable Number of Models in One Form

This is a great tutorial and thanks to a new gem, ActivePresenter, things are looking a lot easier for working with multiple models in a single form.

http://jamesgolick.com/2008/7/28/introd … ready-know

Lots of the logic and RJS that Ryan describes could easily be modified to work with ActivePresenter as well.  It doesn't support building multiple child model records yet but that will soon be supported (which is a major point of this tutorial).  But the promise is there.

Last edited by MDWeezer (2008-08-12 09:31:52)

Re: Creating Variable Number of Models in One Form

Thanks for this post - I searched high and low for this information and only came across this tutorial after several days of Googling. And I was able to port this to work with jRails with very little modifications.

139

Re: Creating Variable Number of Models in One Form

Thanks for this post - It almost got me there!

I've tried to apply this example to my application without much luck. I'd like to create a form with multiply records. The parent records are already created and now need to be able to add N number of child records from a single form (tabular format, 5 columns per row).

The examples show this processing through the parent (project) controller - how would this be approached if going through the child controller?

I'm currently using rails 2.3.2

------------------- Thrown Exception --------------------------------------
Showing app/views/timeslips/_newform.html.erb where line #16 raised:

undefined method `each_with_index' for #<Timeslip:0xb6e1619c>

Extracted source (around line #16):

13:   <p>
14:   <h2>Timeslips</h2>
15:   <div id="timeslips">
16:     <% @timeslip.each_with_index do |timeslip, index| %>
17:       <%= render :partial => 'timeslip_fields', :locals => { :timeslip => timeslip, :index => index } %>
18:     <% end %>
19:   </div>