Recently, I had to come up with a multiple file upload form that works with the file_column plugin. My site was already using mootools as it’s main JS framework so I wanted to come up with a solution that would be mootools friendly.
Luckily, I found this great mootools plugin that handles multiple file upload in an elegant way, so I decided to start with that as a base.
I had to modify the script, mostly because file_column requires a hidden field for every file field there are in your form. I provided a link to this modified version at the bottom of this post.
Here is a step by step guide to make this work (I am assuming you are familiar with file_column already).
For this example, let’s pretend I have the following models:
- User (my user model)
- UserPicture (a picture uploaded by a user)
My UserPicture model has 2 attributes: user_id and image(the file_column). The relationships are as follow: User has_many UserPictures, and UserPicture belongs_to User
I will use 1 view to allow the user to upload pictures. That view will contain the form with the file fields. This is what the view’s code looks like:
-
<h1>Picture Upload</h1>
-
<%= javascript_include_tag "Stickman.MultiUpload.js" %>
-
<script type="text/javascript">
-
window.addEvent('domready', function(){
-
new MultiUpload( $( 'main_form' ).user_picture, 3, '[{id}][image]', true, true, '[{id}][image_temp]' );
-
});
-
</script>
-
<form id="main_form" method="post" enctype="multipart/form-data" action="/users/uploadpictures">
-
<input name="user_picture" type="file" />
-
<br clear="all" />
-
<%= submit_tag "Submit" %>
-
</form>
The important parts are: My file input needs to have the class name as it’s “name” attribute, in this case; user_picture. If your model name is different, change the file input’s name to reflect your model name. Also, if your file_column’s name is NOT “image”, you need to change this line:
-
new MultiUpload($('main_form').user_picture, 3, '[{id}][image]', true, true, '[{id}][image_temp]');
So it reflects your file_column’s name (change both [image] and [image_temp]) so if your file_column’s name is “picture”, this line would become:
-
new MultiUpload($('main_form').user_picture, 3, '[{id}][picture]', true, true, '[{id}][picture_temp]');
Next is your controller. In this case, I chose to send the form to “uploadpictures” action of the “users” controller. This is what this controller needs to look like:
-
def uploadpictures
-
params[:user_picture].each do |id, image|
-
@user_picture = UserPicture.new(image)
-
@user_picture.user_id = @current_user.id
-
@user_picture.save
-
end
-
end
So basically, for each user_picture in the params, I create a new UserPicture model instance, passing the “image” parameter… For my own needs, I have to track the user_id too so the picture is associated to a user. This could be done with a hidden field in the upload form, in my case, sessions are already taking care of it.
And that’s it basically… all the pictures should be uploaded correctly, following file_column’s directory structure, and inserted in the database.
NOTE: In my example, mootools was included in my layout, so I didn’t need to re-include it, but YOU WILL need to include it BEFORE your include the multiple upload script.
To get it working with my modified version, just replace the .js file with mine, and put it in /public/javascripts.
To get the CSS working, I just copied the code of the .css file and added it to my own stylesheet (it shouldn’t overwrite any of your styles but double check to make sure).
And finally, I placed the image that came with it under /public/images/cross_small.gif
The modified version of the Multiple File Upload script can be found here. I suggest you also download the original version here to get the CSS and image file that comes with it.
8 Comments
I made a Flash multiple file upload applet that includes a rails plugin to make it easy to use. It’s licensed under the LGPL, and is very customizable. It is extensively documented, and usage screencasts are available. Check it out at http://multibitshift.com.
JC
Nice work! Flash multi-upload is definitely sexier! :) I’ll probably use it somewhere eventually, and offer my version on the side as a non-flash alternative (for those who *still* don’t have flash installed ;) )
Thank you for the detailed instructions of multi-file upload using file_column.
Do you know how we can add validation for the total file size of all objects prior to submitting a multi-file upload?
Hello, I´m kind of a newbie with RoR, I built a model where a user can have up to 5 images uploaded which are stored in the same model. I have a view which helps the user edit the information he is adding to his post. In this view I would like the user to be able to change the uploaded images (which up to now can be done without problems) and even delete one or two etc images without having to delete his entire posting.
I´ve been searching for this some days from now and havent found anything. I saw in one forum a guy who tried setting the database filename column for the record to “NULL” or ”” and that did not work for the user so he had to build separate models the pictures, which I don´t want to do unless there is no other option.
I would appreciate any help. Thanks!
Thanks for the time saver. I already had a multi file upload setup, but I needed a clean and efficient script to allow for multiple inputs. Your tutorial provided those very nicely :].
Hey glad my post could be useful to someone! ;)
Thanks so much! It took me a lil while to get this working but I got it! Much thanks again!
Hello.
I am a bit confused about how to make mootools a main js-framework for rails? So that _remote functions could also work through it and all effects as well.