I have a form for creating an album like following:
# app/views/albums/new.html.erb
<h2>Details of Album</h2>
<% form_tag albums_path, :multipart => true do %>
<%= label_tag "Name" %><br />
<%= text_field_tag :name %><br />
<br />
<%= render(:partial => 'photos/photo_form') -%>
<%= link_to "Add another photo", '#', :id => 'addPhotoLink' %><br />
<br />
<%= submit_tag "Create Album" %>
<% end %>
In my application.js file I have following function
addPhotoForm: function () {
$('#addPhotoLink').click(function () {
$.get('/photos/new', null, function (data) {
$('#addPhotoLink').before(data);
}, 'script');
return false;
});
}
The PhotosController#new looks like following
def new
respond_to do |format|
format.js
end
end
Following is corresponding view:
<%= render(:partial => 'photo_form') -%>
And photo_form
partial
# app/views/photos/_photo_form.html.erb
<%= label_tag "Photo" %><br />
<%= file_field_tag 'photos[][image]' %><br />
<br />
<%= label_tag "Caption"%><br />
<%开发者_如何学Go= text_field_tag 'photos[][caption]' %><br />
<br />
<%= label_tag "Tags(comma separated)" %><br />
<%= text_field_tag 'photos[][tags]' %><br />
<br />
When I click on "Add another photo", photo_form appears perfectly well. When I specify image file, caption and tags for all the instances of photo forms, attributes sent to the server arrive perfectly well. Like below:
Processing AlbumsController#create (for 127.0.0.1 at 2010-12-08 18:39:52) [POST]
Parameters: {"name"=>"Crap", "commit"=>"Create Album", "photos"=>[{"tags"=>"skeleton, haddi, raja", "caption"=>"Hockey", "image"=>#<File:/tmp/RackMultipart20101208-10630-spoii-0>}, {"tags"=>"yoda, star, wars, star wars", "caption"=>"Yoda", "image"=>#<File:/tmp/RackMultipart20101208-10630-2rwp4s-0>}], "action"=>"create", "authenticity_token"=>"RaK8fdFo0cPoYOTIU7amt6GVnF0/5ss7xgX3Nfd9FjI=", "controller"=>"albums"}
However when I do not populate first file input type with path to a file on disc, and specify a path to a file in second photo form instance, attributes sent to the server do not arrive in correct order. Like below:
Processing AlbumsController#create (for 127.0.0.1 at 2010-12-08 19:59:20) [POST]
Parameters: {"name"=>"", "commit"=>"Create Album", "photos"=>[{"tags"=>"", "caption"=>"", "image"=>#<File:/tmp/RackMultipart20101208-10630-1iozpwx-0>}, {"tags"=>"reddit, alien, ,", "caption"=>"Reddit Alien idle"}], "action"=>"create", "authenticity_token"=>"Rrk88xJdXpp96SN8zS7dySTWwnmp8UJlTBksu4xtkkU=", "controller"=>"albums"}
see the 'photos' key in above parameters list. The image that was specified in the second photo form instance comes in the first hash whereas it should have been present in the second hash.
What am I doing wrong?
If I change the javascript function to look like following, everything works perfectly well.
addPhotoForm: function () {
$('#addPhotoLink').click(function () {
$(this).before('<label for="Photo">Photo</label><br /><input id="photos__image" name="photos[][image]" type="file" /><br /><br /><label for="Caption">Caption</label><br /><input id="photos__caption" name="photos[][caption]" type="text" /><br /><br /><label for="Tags_comma_separated_">Tags(comma separated)</label><br /><input id="photos__tags" name="photos[][tags]" type="text" /><br /><br />')
return false;
});
Where before
is passed html equivalent to app/views/photos/_photo_form.html.erb
.
EDIT: Following is the HTML that is produced by browser(Firefox 3.6.12)
<h2>Details of Album</h2>
<form action="/albums" enctype="multipart/form-data" method="post"><div style="margin:0;padding:0"><input name="authenticity_token" type="hidden" value="Rrk88xJdXpp96SN8zS7dySTWwnmp8UJlTBksu4xtkkU=" /></div>
<label for="Name">Name</label>
<input id="name" name="name" type="text" /><br />
<br />
<label for="Photo">Photo</label><br />
<input id="photos__image" name="photos[][image]" type="file" value="" /><br />
<br />
<label for="Caption">Caption</label><br />
<input id="photos__caption" name="photos[][caption]" type="text" /><br />
<br />
<label for="Tags_comma_separated_">Tags(comma separated)</label><br />
<input id="photos__tags" name="photos[][tags]" type="text" /><br />
<br />
<a href="#" id="addPhotoLink">Add another photo</a><br />
<br />
<input name="commit" type="submit" value="Create Album" />
</form>
I've seen this before and it occurred when one of the hash values was empty. Rails seems to take the first few different keys and combines them as one set of attributes in a hash, then takes the next few and combines them. So, an attribute that shows up later in the post will be added to an earlier hash in the array (what's happening to you)
This was happening to me with a check_box, but it looks like that happens with a file field as well. You can experiment - add a hidden field before the file field with the same name to see if that submits an empty string by default.
精彩评论