1
votes

I am trying to implement Dropzone.js as a Drag and drop profile photo uploader for the User scaffold

In my ruby on rails I've created user scaffold, that has a profile photo (the implementation is handled by PaperClip).

I want to create an experience that

  1. A User edits all details on the same page (including profile photo)
  2. On the first load of the edit/user/x page the current image is loaded;
  3. When the user has dropped the image over the form section, the image is rendered as a preview.
  4. If you click cancel, your previous image will be restored.

The approach I have come up with is to create a temp Uploads table that stores all images/files that are dropped into Dropzone. Upon successful upload, it will return the id of the image to the form, and then once the user clicks save, the id of the image will be posted with the form, and a link between the User and the Image will be created.

I have 2 questions for the stack overflow community:

  1. Am I overcomplicating this approach?
  2. I am getting the following error: ActionController::ParameterMissing (param is missing or the value is empty: Upload): What have I done Wrong?

The code I have so far is outlined below.

Any help is appreciated.

<%= form_with(model: user, local: true) do |form| %>
<div class="form-group">
    <% if user.errors.any? %>
      <div id="error_explanation" class="row">
        <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
        <ul>
        <% user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
        </ul>
      </div>
    <% end %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name, id: :user_name, :class=> "form-control" %>
  </div>
  <div id="profile-photo" class="field dropzone">
    <%= form.file_field :profile, :class=> "fallback"%>
  </div>

  <div class="field">
    <%= form.label :role %>
    <%= form.text_field :role, id: :user_role, :class=> "form-control" %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
</div>
<% end %>

I have the following JavaScript

 $("#profile-photo").dropzone({
      url: '/uploads/upload',
      maxFiles: 1,
      maxfilesexceeded: function(file) {
          this.removeAllFiles();
          this.addFile(file);
      },
      success: function(file, response){
        alert("upload was successful");
      }
    });

The following Controller#Action

# POST /uploads
    # POST /uploads.json
    def upload
      puts request.request_parameters
      @upload = Upload.new(upload_params)

        if @upload.save
           puts @upload.id
      #     format.html { redirect_to @upload, notice: @upload.id }
      #     format.json { render :show, status: :created, location: @upload }
          else
      #     format.html { render :new }
      #     format.json { render json: @upload.errors, status: :unprocessable_entity }
        end
    end

    def upload_params
      params.require(:Upload).permit(:photo)
    end

My request.request_parameters looks like the following:

Parameters: {"file"=>#<ActionDispatch::Http::UploadedFile:0x007f8fe120b278 @tempfile=#<Tempfile:/var/folders/rp/79zzx36504z9kp7srj55pxk80000gn/T/RackMultipart20170804-3814-13pid57.jpg>, @original_filename="tokyo.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"file\"; filename=\"tokyo.jpg\"\r\nContent-Type: image/jpeg\r\n">}
1
Hi Anthony! Were you ever able to get this resolved? Running in to a similar issue myself... - Spectator6

1 Answers

0
votes

I suspect this has to do with what the dropzone.js file uses as the paramName. If you open the dropzone.js file, you'll see the paramName value defaults to 'file'.

Try updating this line to read as follows:

paramName: 'user[profile]' (or however you have your user model's file field attribute set up, I just inferred this from your post and could have it wrong here)

For example, in my case, my Images table has a column named 'file' which is where the image is uploaded. Once I updated the paramName to be 'image[file]' everything started working as expected and the strong params were populated appropriately with the POST request.