Search code examples
ruby-on-railscarrierwaveimage-uploadingcdncloudinary

Carrierwave Cloudinary image upload works but null values returned right after upload


First of all, let me say - Cloudinary and Carrierwave are both amazing. Carrierwave, super simple image uploading.

Cloudinary offering free plan with 10GB of storage, very generous.

My Problem

I'm basically testing Cloudinary with Carrierwave.

I've got them both to work in the sense that when I create a new user (or update existing one) with an image file attachment using Postman app on my Mac, the images actually do get saved on the Cloudinary CDN and the URL values in my database afterwards but the JSON response values for avatar are null:

Postman screenshot

The problem you can see in the returned response, the avatar field all contains null values.

However, when I view my index action of my UsersController in my browser, the avatar values show up:

JSON response

Any ideas what might be causing this issue?

Could it be that by the time the User entity is created/updated, Cloudinary hasn't finish uploading the info quite in time yet and so Carrierwave saves the value as null and later, when Cloudinary has finished processing, it makes a callback to Carrierwave to update the values?

I'm not doing anything fancy, just basic code:

UsersController

class UsersController < ApplicationController
  def index
    users = User.all
    render json: users
  end

  def create
    user = User.new(user_params)

    if user.save
      render json: user, status: :created
    else
      render json: user.errors, status: :unprocessable_entity
    end
  end

  def update
    # simple test, change to params id later
    user = User.where(id: 3)

    if user.update(user_params)
      render json: user, status: :ok
    else
      render json: user.errors, status: :unprocessable_entity
    end
  end

  private
  def user_params
    params.permit(:id, :first_name, :last_name, :email, :password, :password_confirmation, :avatar)
  end
end

Mac Terminal output

Processing by UsersController#update as */*
  Parameters: {"avatar"=>#<ActionDispatch::Http::UploadedFile:0x007fa39caad5b0 @tempfile=#<Tempfile:/var/folders/sk/tjj1jxkd62ngkhfxmh8yc04r0000gn/T/RackMultipart20170918-2307-lw2ga8.jpg>, @original_filename="doc.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"avatar\"; filename=\"doc.jpg\"\r\nContent-Type: image/jpeg\r\n">, "first_name"=>"Emmett", "last_name"=>"Brown", "id"=>"3"}
Can't verify CSRF token authenticity.
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ?  [["id", 3]]
   (0.1ms)  begin transaction
  SQL (0.4ms)  UPDATE "users" SET "first_name" = ?, "avatar" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["first_name", "Emmett"], ["avatar", "kzc9ghjln9gfoowhzudi.png"], ["updated_at", "2017-09-18 02:55:59.269637"], ["id", 3]]
  SQL (0.1ms)  UPDATE "users" SET "avatar" = 'image/upload/v1505703360/kzc9ghjln9gfoowhzudi.png' WHERE "users"."id" = ?  [["id", 3]]
   (2.7ms)  commit transaction
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::JsonApi (3.52ms)
Completed 200 OK in 3259ms (Views: 14.9ms | ActiveRecord: 4.0ms)

Hopefully it's some silly mistake or quick configuration option that I am not aware of and not some bug on either Carrierwave or Cloudinary's side.

Has anyone encountered this problem before?


Solution

  • Umm...okay, I think I found a solution/work around?

    Maybe some Rails or Carrierwave devs can explain to me why I need to do this to fix the problem:

    def create
      user = User.new(user_params)
    
      if user.save
        # -------------------------------------------------
        # NEED TO RELOAD FOR CARRIERWAVE
        # -------------------------------------------------
        user.reload 
    
        render json: user, status: :created
      else
        render json: user.errors, status: :unprocessable_entity
      end
    end
    

    Seems like an extra step which can impact system performance.

    I shouldn't need to do this right?