具有嵌套属性的Carrierwave和Dropzone

时间:2015-10-08 16:44:18

标签: ruby-on-rails file-upload carrierwave nested-attributes dropzone.js

我一整天都在努力争取这个解决方案。

在我的应用程序中,用户可以创建一个属性并为该属性上传许多照片,如这些模型所定义:

Property.rb:

class Property < ActiveRecord::Base
   belongs_to :user

   has_many :attachments, dependent: :destroy
   accepts_nested_attributes_for :attachments, allow_destroy: true
end

Attachment.rb:

class Attachment < ActiveRecord::Base        
    mount_uploader :photo, PhotoUploader
    validates_presence_of :photo

    belongs_to :property        
end

如您所见,Attachment使用Carrierwave上传器上传图片。

这是我的控制器中定义的创建方法,非常简单:

properties_controller.rb

def create
    @property = current_user.properties.build(property_params)

    if @property.save
        save_photos
        flash[:notice] = "Your property has been created."
        redirect_to @property
    else 
        flash[:alert] = "Something went wrong."
        render :new
    end
end

这些是强大的参数并保存照片方法:

def property_params
   params.require(:property).permit(:name, :price, :address, :department, :type_id, :description, attachment_attributes: [:id, :property_id, :photo])
end

def save_photos
   # Create Each Uploaded Photo
   params[:attachments]['photo'].each do |photo|
      @attachments = @property.attachments.create!(:photo => photo)
   end
end

截至目前,文件上传的工作原理与此类似,不使用Dropzone。但是,当我想将Dropzone集成到我的表单中时,就会出现问题。

我已将 dropzone 类添加到我的表单中,从视图:

_form.html.haml

= f.fields_for :attachments do |at|
   = f.file_field :photo, :multiple => true, name: "attachments[photo][]"

现在,在我的dropzone配置文件中:

properties.js

$(document).ready(function(){
  // disable auto discover
  Dropzone.autoDiscover = false;

  // grap our upload form by its id
  $("#new_property").dropzone({
    // restrict image size to a maximum 1MB
    maxFilesize: 5,

    // changed the passed param to one accepted by our rails app
    paramName: "attachments[photo]",

    // show remove links on each image upload
    addRemoveLinks: true,
    dictDefaultMessage: "Arrastre sus fotos aqui.",
    autoProcessQueue: false,
    uploadMultiple: true,
    parallelUploads: 5,
    maxFiles: 5,


     // The setting up of the dropzone
    init: function() {
      var myDropzone = this;

      // First change the button to actually tell Dropzone to process the queue.
      this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
        // Make sure that the form isn't actually being sent.
        e.preventDefault();
        e.stopPropagation();
        myDropzone.processQueue();
      });

      // Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
      // of the sending event because uploadMultiple is set to true.
      this.on("sendingmultiple", function() {
        // Gets triggered when the form is actually being sent.
        // Hide the success button or the complete form.
      });
      this.on("successmultiple", function(files, response) {
        // Gets triggered when the files have successfully been sent.
        // Redirect user or notify of success.
      });
      this.on("errormultiple", function(files, response) {
        // Gets triggered when there was an error sending the files.
        // Maybe show form again, and notify user of error
      });
  }




  });
});

此代码包含使用表单的配置,只有在提交整个表单时才会上传照片,如this tutorial中所述。

因此,一旦实现了dropzone,我可以毫无问题地删除文件。但是,当我尝试上传表单时,似乎无法识别照片文件参数。我收到以下错误:

  

PropertiesController中的NoMethodError #create undefined method` []'   为零:NilClass   在线:params [:附件] ['照片']。每个人都这样做   |照片|

似乎只要我添加了dropzone,参数就会消失并变为零。我尝试使用dropzone配置中的 nameParam 属性,但都无济于事。

非常感谢帮助...

1 个答案:

答案 0 :(得分:1)

嗯..嗯..我知道它已经很晚了,但我有一个答案。

您的表单名称是public LinkedListNode remove(LinkedListNode head, int value) { if( head == null) return head; LinkedListNode current = head; LinkedListNode trailcurrent = null; while(current != null) { if(current.value == value) { if(current == head) { head = head.next; current = head; } else{ trailcurrent.next = current.next; current = trailcurrent.next; } } else { trailcurrent = current; current = current.next; } } return head; } 对吗?

你的dropzone应如下所示:

attachments[photo][]

解决方案就在这里:

paramName: attachments[photo]
uploadMultiple: true

您只需要弹出包含文件的最后一个数组值。因为在dropzone中,当您添加def save_photos # Create Each Uploaded Photo params[:attachments]['photo'].each do |photo| @attachments = @property.attachments.create!(:photo => photo.pop) end end 时,输出将为uploadMultiple: true所以[0, file1], [1, file2] and etc.将获得photo.pop并推送到数据库。