2
votes

I am trying to upload multiple images using Carrierwave and Dropzone.js however I am getting following error when I submit the form.

Please note that the same form without dropzone.js is working fine, meaning when I am simply using HTML5 to upload multiple images.

Please see below hash which is created when I submit the form (through ajax using dropzone)


"project_images_attributes"=>[{"image"=

[#, @original_filename="artist4.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"project[project_ images_attributes][][image][]\"; filename=\"artist4.jpg\"\r\nContent-Type: image/jpeg\r\n">, #, @original_filename="feed1.jpg", @con tent_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"project[project_images_attributes][][image][]\"; filename=\"feed1.jpg\"\ r\nContent-Type: image/jpeg\r\n">, #, @original_filename="gallery1.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"project[project_images_attributes][][image][]\"; filename=\"gallery1.jpg\"\r\nContent-Type: image/jpeg\r\n">]}]}, "project-vide o"=>[""], "commit"=>"Create project"}

Unpermitted parameters: image

Please note I have whitelisted the image params in my controller and also it's working using HTML 5 but not using ajax and dropzone.js

Does anyone know how to fix this ?

Thank you

2
Share the relevant code from the controller where you have whitelisted the attributes.Kirti Thorat

2 Answers

0
votes

Code to contextualize where I ended up:

  private
  def pin_image_params
    #params.require(:pin_image).permit(:photo) (not permitted)
    #params.require(:pin_image).permit(photo: [:'0']) (permitted but action handler error)
    #params.require(:pin_image)["photo"].values.first (stringify_keys error)
    params.require(:photos).values
  end

The strong params kept returning unpermitted params :photo. Looking in console, I saw that the params were getting numbered, and the only way I could access them was to dive in by number. Even then though, trying to pass them in directly to create returned errors. This was because the model can't understand the format of the numbered hash. It's not smart enough to know it needs to iterate through each attached image. So:

def create
   # so pin_image_params is an array of files basically
   @pin_images = pin_image_params.inject([]) do |memo, photo|
   # this pattern will store the memo into the @pin_images reference
      memo << PinImage.create(photo: photo)
   # keying it explicitly
   end
   if @pin_images.present?
      render json: { id: @pin_images.map(&:id) }, :status => 200
   else
      #  you need to send an error header, otherwise Dropzone
      #  will not interpret the response as an error:
      render json: { error: @pin_images.errors.full_messages.join(',')}, :status => 400
   end
end

My controller returns a list of ids, and those are captured in a hidden field for the model that owns PinImage (Pin). (That's done in a success callback on the ajax that submits the PinImages via dropzone.) So when the primary model is submitted, I also have to handle doing the association there, but I find I am preferring that to muddling through nested_attributes_for. YMMV.

0
votes

Have a look at the way you submit your form. Is it form.submit? Dropzone automatically submits the file through ajax once uploading is finished