具有嵌套属性的Carrierwave和Dropzone

时间:2022-11-23 20:40:50

I have been battling with this all day and can't seem to figure out the solution.

我一整天都在与这个斗争,似乎无法找出解决方案。

In my application, a user can create a Property and upload many photos for that property, as defined by these models:

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

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

As you can see, Attachment uses Carrierwave uploader for uploading the picture.

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

This is the create method defined in my controller, very simple:

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

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

And these are the strong parameters and save photos methods:

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

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

As of now, file uploading works like this without using Dropzone. However, when I want to integrate Dropzone into my form, this is where the problem arises.

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

I have added the dropzone class to my form, from the view:

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

_form.html.haml

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

Now, on my dropzone configuration file:

现在,在我的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 code includes configuration to work with the form in a way that the photos will only be uploaded when the whole form gets submitted, as explained in this tutorial.

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

So once dropzone is implemented, I can drop the files with no problems. However, when I try to upload the form, it seems it cannot recognize the photo files parameters. I get the following error:

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

NoMethodError in PropertiesController#create undefined method `[]' for nil:NilClass on line: params[:attachments]['photo'].each do |photo|

PropertiesController中的NoMethodError#创建未定义的方法`[]'为nil:NilClass on line:params [:attachments] ['photo']。每个都做|照片|

It seems that as soon as I add the dropzone, the parameters just vanish and become nil. I have tried toying with the nameParam attribute in the dropzone configuration, but all to no avail.

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

Help is greatly appreciated...

非常感谢帮助......

1 个解决方案

#1


0  

Erm.. I know it's late but I have an answer for this.

呃..我知道现在已经晚了,但我有一个答案。

your form name is attachments[photo][] right?

你的表格名称是附件[照片] []对吗?

your dropzone should look like this:

你的dropzone应该是这样的:

paramName: attachments[photo]
uploadMultiple: true

The solution is in here:

解决方案在这里:

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

You just need to pop the last array value which contains the files. Since in dropzone, when you add uploadMultiple: true the output will be [0, file1], [1, file2] and etc. So photo.pop will get [file1] [file2] etc. and push to the database.

您只需要弹出包含文件的最后一个数组值。因为在dropzone中,当你添加uploadMultiple:true时,输出将是[0,file1],[1,file2]等。所以photo.pop将获得[file1] [file2]等并推送到数据库。

#1


0  

Erm.. I know it's late but I have an answer for this.

呃..我知道现在已经晚了,但我有一个答案。

your form name is attachments[photo][] right?

你的表格名称是附件[照片] []对吗?

your dropzone should look like this:

你的dropzone应该是这样的:

paramName: attachments[photo]
uploadMultiple: true

The solution is in here:

解决方案在这里:

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

You just need to pop the last array value which contains the files. Since in dropzone, when you add uploadMultiple: true the output will be [0, file1], [1, file2] and etc. So photo.pop will get [file1] [file2] etc. and push to the database.

您只需要弹出包含文件的最后一个数组值。因为在dropzone中,当你添加uploadMultiple:true时,输出将是[0,file1],[1,file2]等。所以photo.pop将获得[file1] [file2]等并推送到数据库。