2

Does anyone have advice/examples on getting the jQuery File Upload plugin working with Rails using nested attributes?

My model "has_many" attachments and accept the necessary nested attributes. I would like to get this working with the jQuery File Upload but haven't been able to find any good examples to get me started.

Has anyone achieved something like this and able to give some direction?

Thanks.

sshefer
  • 239
  • 4
  • 14

4 Answers4

4

I've succesfuly set it up to work when editing a model with nested attachments.
The same is not possible when creating a new model - at least not currently due to paperclip.

You have to set up some jQuery File Upload options which I found here.

You should call fileUploadUI() on the whole form, and set file input wrapper element as dropZone. You should also set url, fieldName and formData accordingly.

Here's how my JS looks like (simplified):

var $file_upload_form = $("form")
var attachable_id     = $file_upload_form.attr("id").match(/_(\d*)$/)[1]
var attachable_type   = $file_upload_form.attr("id").match(/edit_(\w*)_\d*$/)[1]

$($file_upload_form).fileUploadUI({
    url         : '/admin/attachments',
    fieldName   : "attachment[data]",
    formData    : [
        {
            name  : 'attachment[attachable_id]',
            value : attachable_id
        },
        {
            name  : 'attachment[attachable_type]',
            value : attachable_type
        }
    ],
    dropZone        : $('#attachments_dropzone'),
    uploadTable     : $('#upload_files'),
    downloadTable   : $('#download_files'),
    buildUploadRow  : function (files, index) {
        var file = files[index];
        return $('<tr><td>' + file.name + '<\/td>' +
                        '<td class="file_upload_progress"><div><\/div><\/td>' +
                        '<td class="file_upload_cancel">' +
                        '<button class="ui-state-default ui-corner-all" title="Cancel">' +
                        '<span class="ui-icon ui-icon-cancel">Cancel<\/span>' +
                        '<\/button><\/td><\/tr>');
    },
    buildDownloadRow: function (file) {
        return $('<tr><td><img alt="Photo" width="40" height="40" src="' + file.pic_path + '">' + file.name + '<\/td><\/tr>');
    }
})
Mirko
  • 5,207
  • 2
  • 37
  • 33
  • Thanks Mirko - After some digging around I basically came to the same conclusion. I'm able to get the file upload for edits but not for new instances. Definitely the most direct, best, answer. :) – sshefer Apr 19 '11 at 20:48
  • This plugin got a major version bump, so this pastie is no longer relevant. New demo is here: http://aquantum-demo.appspot.com/file-upload – Mirko Sep 02 '11 at 16:51
0

I spent a long time getting it to work in a project of mine. Here's a link to a giant SO post I made on a different question. It may help you.

Rails 3 + JQuery-File-Upload + Nested Model

Community
  • 1
  • 1
Kyle Carlson
  • 7,967
  • 5
  • 35
  • 43
0

I have coped with this problem and made a demo app to show how to do this.

In short I have two models: item and upload.

item.rb:

has_many :uploads
accepts_nested_attributes_for :uploads, :allow_destroy => true

upload.rb:

belongs_to :item
    has_attached_file :upload, :styles => { :large => "800x800", :medium => "400x400>", :small => "200x200>" }

I added uploads_attributes to item controller.

Now you can add jquery-file-upload form to your view, but there is one problem: it sends each photo in separate requests. So there is my jquery-file-upload initializer, which uploads all photos in one request (creating item model) and then redirecting to the root of your app (you need to use item form):

<script type="text/javascript" charset="utf-8">
    var num_added = 0;
    var added = 0;
    var all_data = {};
    $(function () {
        // Initialize the jQuery File Upload widget:
        $('#fileupload').fileupload({
          complete: function (e, data) {
            window.location = "<%= root_url %>";
        },
          singleFileUploads: false
        })  .bind('fileuploadadd', function (e, data) {num_added++;})
            .bind('fileuploadsubmit', function (e, data) {
            if(added < num_added)
            {
            if (added == 0)
            all_data = data;
            else
            {
            $.each(data['files'], function(i, file){
            all_data['files'].push(file);
            });
            $.each(data['context'], function(i, context){
            all_data['context'].push(context);
            });
            }
            added++;
            if (added == num_added)
            {
            added++;
            all_data.submit();
            }
            return false;
            }
            })
            .bind('fileuploadsend', function (e, data) {num_added = 0; added = 0;});

        // 
        // Load existing files:
        $.getJSON($('#fileupload').prop('action'), function (files) {
          var fu = $('#fileupload').data('blueimpFileupload'), 
            template;
          fu._adjustMaxNumberOfFiles(-files.length);
          console.log(files);
          template = fu._renderDownload(files)
            .appendTo($('#fileupload .files'));
          // Force reflow:
          fu._reflow = fu._transition && template.length &&
            template[0].offsetWidth;
          template.addClass('in');
          $('#loading').remove();
        });

    });
  </script>
goooseman
  • 619
  • 5
  • 12
  • This looks like a great project! I'm adapting it to mine but can't seem to get around the auto upload (which is actually set to False by default). Did you have to do anything special to get that working? Mine isn't auto-uploading, although the cancel button is showing. Initial thoughts? – panzhuli Dec 03 '13 at 05:06
  • I didn't do anything special with autoupload. In my case I needed user to choose all his pictures and then press Upload button by himself. – goooseman Dec 04 '13 at 07:09
  • And why you don't need cancel button? OK, you can easily hide it with CSS or find in html and delete it. – goooseman Dec 04 '13 at 07:10
  • I see the form trying to submit with blob:http://localhost:5000/somestring. but the app isn't responding... I'll start a new thread! – panzhuli Dec 04 '13 at 16:27
0

Take a look at the 7 minute mark of this video. http://ror-e.com/info/videos/3

It describes a way to upload images "product has_many images" You should look at the ror_ecommerce source and in admin/merchandise/images/products you can look at the code.

https://github.com/drhenner/ror_ecommerce

The JS is in application.js and the application_helper.rb

drhenner
  • 2,200
  • 18
  • 23