Как использовать jquery-fileupload для вложенных вложений?

Я использую jquery-fileupload-rails для загрузки нескольких файлов.

Я хочу получить возможность задавать имя документа и добавлять к нему несколько вложений.

Но прямо сейчас, когда я выбираю 3 вложения, он создает 3 documents каждый с одним вложением.

Думаю, мне нужно как-то изменить форму для добавления вложений. Я добавил несколько опций и галообразное имя.

Я хочу использовать этот плагин, потому что позже мне захочется добавить функцию перетаскивания.

С

= 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

Генерация:

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

JS

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

Модели

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

контроллер

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

Ответ 1

Я сделал что-то подобное с двумя отдельными формами. В принципе, вы создаете форму для документа с полем имени и скрытым полем для attachment_ids, а затем формой для вложений. Вы можете загружать вложения отдельно (они, к сожалению, были потеряны в то время в архивах), а затем обновить скрытое поле под документами с идентификаторами вновь созданных записей вложений.

В основном, создайте ответ json от контроллера вложений, включая идентификатор вновь созданного объекта. Затем создайте функцию javascript, чтобы добавить вновь созданный идентификатор из каждого успешного обратного вызова в скрытое поле.

Я уверен, что есть более простой способ сделать это, но я всегда немного зациклен многопользовательскими загрузками и вложенными атрибутами.

EDIT: Итак, я нашел старый код и портирую его.

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

Затем вы либо создаете файл create.js.erb в скриншотах

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(', ');
});

Это может быть, например, вызов рендеринга экрана, но отображать его, но вы хотите в частичном.

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

В форме документов создайте

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

Другой способ сделать это - ответить json, а в завершенном обратном вызове fileupload добавить json ID нового приложения в скрытое поле.

Вам нужно будет разбирать любой беспорядок с помощью hidden_ids, вероятно, лучше, чем просто .split(',')

У меня не было возможности слишком внимательно смотреть на это.

Надеюсь, это поможет.