Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use jquery-fileupload for nested attachments?

I am using jquery-fileupload-rails for multiple files uploading.

I want to achieve ability to set name of document and adding to it multiple attachments.

But right now when I choose 3 attachments it creates 3 documents each one with one attachment.

I guess I need to change somehow form for adding attachments. I added multiple option and harcoded name.

I want to use this plugin because later I will want to add drag-and-drop feature.

From

= simple_form_for [:member, @document], html: { multipart: true } do |f|
  = f.input :name
  = f.simple_fields_for :attachments, Attachment.new do |a|
    = a.file_field :attachment, multiple: true, name: "document[attachments_attributes][][attachment]"
  = f.submit

Generate:

<input id="document_attachments_attributes_0_attachment" multiple="multiple" name="document[attachments_attributes][][attachment]" type="file">

JS

jQuery ->
    $('#new_document').fileupload()

Models

class Document < ActiveRecord::Base
  has_many :attachments
  accepts_nested_attributes_for :attachments
end

class Attachment < ActiveRecord::Base
  belongs_to :document

  has_attached_file :attachment
end

Controller

class Member::DocumentsController < ApplicationController
  def new
    @document = Document.new
  end

  def create
    @document = Document.new params[:document]

    if @document.save
      redirect_to member_documents_path, notice: "Created"
    else
      redirect_to member_documents_path, alert: "Not created"
    end
  end

  private

  def document_params
    params.require(:document).permit(:name, attachments_attributes: [:attachment])
  end
end
like image 762
tomekfranek Avatar asked Nov 06 '13 12:11

tomekfranek


Video Answer


1 Answers

I've done something similar with two separate forms. Basically, you create a form for a document with a name field and a hidden field for attachment_ids, and then a form for attachments. You could upload the attachments separately (they would unfortunately be orphaned records at the time), and then update a hidden field under documents with the ids of the newly created attachment records.

So basically, create a json response from the attachments controller, including the id of the newly created object. Then create a javascript function to add the newly created ID from each success callback to the hidden field.

I'm sure there's an easier way to do this, but I always get a little stumped by multifile uploading and nested attributes.

EDIT: So I found some old code and am porting it over.

class Member::AttachmentsController < Member::BaseController

  def create
    @attachment = Attachment.create!(params[:attachment])
    # TWO APPROACHES, render json view, or respond with a .js view create.js.erb
    # render json: @attachment.to_json

  end

end

class Member::DocumentsController < Member::BaseController

  def create
    @document = Document.new params[:document]
    @attachments = Attachment.find(params[:attachment_ids].split(','))
    if @document.save
      @document.attachments = @attachments
      redirect_to member_documents_path, notice: "Created"
    else
      redirect_to member_documents_path, alert: "Not created"
    end
  end
end

Then you either create a create.js.erb in screenshots

var screenshotContainer, 
    idContainer;

screenshotContainer = $('#attachments');
idContainer =  $('#attachment_ids_hidden_field');  

screenshotContainer.append('<%= j render @attachment %>');

idContainer.val(function(i, v) {
  var arr = v.split(', ');
  arr.push('<%= @attachment.id %>');
  return arr.join(', ');
});

This might be a screenshot render call for example, but display it however you want in the partial.

<%= image_tag(attachment.attachment, size: "100x100", data: { attachment_id:     attachment.id }) if attachment.attachment? %>

In the documents form create

<input type="hidden" id="attachment_ids_hidden_field" value="" name="attachment_ids">

The other way to do this is to respond with json, and in the done callback of the fileupload add the json ID of the new attachment to the hidden field.

You'll need to parse whatever mess of the hidden_ids probably better than just a .split(',')

I haven't had a chance to look this over too closely.

Hopefully it helps.

like image 150
csahlman Avatar answered Sep 28 '22 01:09

csahlman