dan
dan

Reputation: 1080

Adding an avatar on user edit

I'm using carrierwave direct to save a user avatar to S3. I've got the example app up and running, but rather than save the avatar when a user is created, I want to be able to add the avatar when the user is edited.

I've made this change to the new method in the avatar controller -

class AvatarsController < ApplicationController
  def new
    @user = User.find_by_id(params[:user_id])
    @uploader = @user.avatar
    @uploader.success_action_redirect = @user
  end
end

... having handed in the :user_id as a parameter in the link_to method.

This upsets S3 -

<Error>
<Code>InvalidPolicyDocument</Code>
<Message>Invalid Policy: Invalid JSON.</Message>
<RequestId>B1546F83A39ABF39</RequestId>
<HostId>
U5vaOy0bh+Zsgb3hKM24PNZvZ7+sh/ntJMJZUmcZ/5uQZIIfzxEDqeymHCO8JJ6w
</HostId>
</Error>

Has anybody got any advice as to how to get to the bottom of the problem?

Upvotes: 1

Views: 263

Answers (1)

ihaztehcodez
ihaztehcodez

Reputation: 2133

It's been a while since I was dinking around with carrierwave direct, but hopefully this will get you pointed in the right direction.

First, understand that carrierwave direct generates a POST policy for you during the call to direct_upload_form_for in your view.

The policy required for making authenticated requests using HTTP POST is a UTF-8 and Base64 encoded document written in JavaScript Object Notation (JSON) that specifies conditions that the request must meet.

So if you want to follow the code, you will find that CarrierWaveDirect::ActionViewExtensions::FormHelper defines direct_upload_form_for, which calls form_for, passing CarrierWaveDirect::FormBuilder as builder.

Looking at CarrierWaveDirect::FormBuilder, we can see that a function required_base_fields defines hidden fields that get included with the form. The one we are interested in particularly is policy.

The value of policy comes from a function by the same name in CarrierWaveDirect::Uploader, which delegates most of its work to a private function generate_policy. Note that it is creating Base64 encoded JSON, exactly as the POST policy requires.

With all this in mind, you can inspect the HTML generated by direct_upload_form_for in the view and get the value of the hidden input with name policy. Then you can decode that value (maybe with Base64.decode64 in rails console) and get human-readable JSON.

Armed with the raw JSON, you can now compare what you are sending to S3 with the specs of the POST policy, and in the context of all the data being sent to s3, you should be able to debug further.

Upvotes: 1

Related Questions