I'm using the madebydna version of Ryan Bates' nested_form gem from GitHub (can be found at https://github.com/madebydna/nested_form). I'm using the forked version for jQuery support as opposed to Prototype.
UPDATE: Check the bottom of the page for an update to this question.
EDIT:
I'm using: RoR v3.0.5, jQuery v1.4.3, Ruby v1.9.2
END EDIT
EDIT: It appears the current structure of the pictures_attributes parameter passed along to the server is causing an issue, at least from what I've seen on other websites. The currently sent structure is as follows:
"pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"5"}}
All other sites I've seen, the pictures_attributes error had the following structure:
"pictures_attributes"=>[{"_destroy"=>"1", "id"=>"5"}]
I'm not sure how to alter my code to make it so the latter occurs, rather than the former. Thoughts?
END EDIT
I followed the directions to a T, the add link works great for adding nested models, but remove fails. In otherwords, I can add multiple fields for a particular model, and those models get created and saved when I submit the form, but when I go to edit the same record again and go to remove the nested models which I just created, they fail to be removed from the associated record.
Here's the nested_form.js script that gets generated after installing the nested_form gem. Forgive but I created a Pastie and reduced it: http://bit.ly/ge5BO7
Here is the pertinent model code:
has_many :pictures, :as => :imageable, :dependent => :destroy
accepts_nested_attributes_for :pictures, :allow_destroy => true, :reject_if => lambda { |a| a[:photo].blank? }
Here is the view code (in the _form.html.erb partial):
<div id="picture_fields">
<% f.fields_for :pictures do |pics| %>
<div class="field">
<%= pics.label :photo, "Photo" %>
<%= pics.file_field :photo %>
<%= pics.link_to_remove "Remove Photo" %>
</div>
<% end %>
<p>
<%= f.link_to_add "Add Photo", :pictures %>
</p>
Here's the generated HTML for one field:
<div class="fields">
<div class="field">
<label for="equipment_pictures_attributes_0_photo">Photo</label>
<input id="equipment_pictures_attributes_0_photo" name="equipment[pictures_attributes][0][photo]" type="file">
<input id="equipment_pictures_attributes_0__destroy" name="equipment[pictures_attributes][0][_destroy]" type="hidden" value="false">
<a href="javascript:void(0)" class="remove_nested_fields">Remove Photo</a>
</div>
<input id="equipment_pictures_attributes_0_id" name="equipment[pictures_attributes][0][id]" type="hidden" value="5">
</div>
And here's the log entry that gets generated when submitting the form:
Started POST "/equipment/494882120" for <ipadd deleted> at 2011-03-24 13:04:18 -0400
Processing by EquipmentController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"98/R6EYCAFd6HwBjMV6bhnfRo6cT7NqPZ9fJ/VEOKKE=", "equipment"=>{"location_id"=>"", "model"=>"fasdf", "serial_number"=>"", "unh_id"=>"", "doc_id"=>"", "purchase_price"=>"", "date_acquired(1i)"=>"2011", "date_acquired(2i)"=>"3", "date_acquired(3i)"=>"24", "comment"=>"", "vendor_id"=>"", "new_vendor_name"=>"", "department_id"=>"320903175", "new_department_name"=>"", "activity_id"=>"", "new_activity_code"=>"", "condition_id"=>"746868371", "new_condition_name"=>"", "pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"5"}}}, "commit"=>"Update Equipment", "id"=>"494882120"}
Equipment Load (0.7ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."id" = 494882120 LIMIT 1
Picture Load (0.4ms) SELECT "pictures".* FROM "pictures" WHERE "pictures"."id" IN (5) AND ("pictures".imageable_id = 494882120 AND "pictures".imageable_type = 'Equipment')
DEPRECATION WARNING: Overwriting validate in your models has been deprecated, please use Base#validate :method_name instead. (called from block in update at /opt/intranet3-dev/app/controllers/equipment_controller.rb:63)
Department Load (0.1ms) SELECT "departments".* FROM "departments" WHERE "departments"."id" = 320903175 LIMIT 1
Condition Load (0.1ms) SELECT "conditions".* FROM "conditions" WHERE "conditions"."id" = 746868371 LIMIT 1
Now, as far as I'm concerned I'm covering all of my bases with allowing the nested objects to be destroyed when _destroy => '1' is encountered in the submitted parameters. However, the object is clearly not being destroyed. Is there an error in the way the parameters are being submitted to the server?
Hopefully someone with a keener eye than I will see some glaring error. Help!
UPDATE:
Okay, I've managed to resolve the problem by taking out the :reject_if clause from my accepts_nested_attributes_for statement. This is a fringe case in the event you have an upload file form, and I dare call it a bug.
In my case I was able to attach photos to my Equipment model, and when editing it would render the form such that the file field was blank (which is what's supposed to happen) for every photo I have attached to my record. After plugging away at this thing for hours, I pondered if the :reject_if clause was causing the controller action to ignore the nested record entirely, even though I told it to destroy the record. Well, it does.
If you have a :reject_if clause, coupled with a :allow_destroy => true, and if the :reject_if evaluates to true YOUR RECORD WILL NOT BE DESTROYED NO MATTER WHAT
I'm currently trying to hack out a method for retaining my :reject_if functionality.
Cheers, Les.