0

I discovered this problem when implementing omniauth-facebook in my application. I could use the facebook graph hash to update the name of my user and their email, but not the photo attribute.

When I try to change the photo (string) attribute of a user, it always updates the value to nil:

@user.update_attributes!(photo: "blah")
   (0.5ms)  BEGIN
  SQL (0.7ms)  UPDATE "users" SET "photo" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["photo", nil], ["updated_at", "2016-07-12 20:43:30.322405"], ["id", 31]]
   (3.0ms)  COMMIT
 => true 

I have a photouploader mounted to my models/User.rb:

mount_uploader :photo, PhotoUploader

And implemented (uploaders/photo_uploader.rb):

class PhotoUploader < CarrierWave::Uploader::Base


  include Cloudinary::CarrierWave
  # Create different versions of your uploaded files:
  version :header do
    process :resize_to_fill => [150, 150]
  end

  version :medium do 
    process resize_to_fill: [100,100]
  end
  version :micro do 
    process :resize_to_fill => [30, 30]
  end
  ...

I believe Cloudinary is the cause because I can manually update any other attribute without issue. How do I override this behavior?

Below is what I am implementing to set the user.photo based on the callback hash from Facebook (where I discovered the problem). The cloudinary hash returns a url as a string just fine; it is not an issue with auth.info.image or the cloudinary upload response.

def self.from_omniauth(auth)
      puts auth
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
        user.email = auth.info.email
        user.first_name = auth.info.first_name  
        cloudinary_hash = Cloudinary::Uploader.upload(auth.info.image)
        user.photo = cloudinary_hash["url"]
        user.last_name = auth.info.last_name
        user.password = Devise.friendly_token[0,20]
      end
    end
Erik V
  • 375
  • 1
  • 4
  • 18

2 Answers2

1

Over the top of my head, I think there are two ways to work around this:

Carrierwave provides a remote_ url that allows you to upload from a remote location. In your case, you would be using:

user.remote_photo_url = auth.info.image # or something like that

The other way I could think of is to use the open method provided by open-uri(required by default in Rails).

You could do:

user.photo = open(auth.info.image)

Let me know if any of these worked for you

oreoluwa
  • 5,553
  • 2
  • 20
  • 27
0

Carrierwave & Cloudinary integration allows you to the the following:

cloudinary_hash = Cloudinary::Uploader.upload(auth.info.image)
preloaded = Cloudinary::Utils.signed_preloaded_image(cloudinary_hash)
user.photo = preloaded

This will later allow you to exploit Carrierwave & Cloudinary for properly generating the different URLs. Can you see if this is working for you in your specific flow?

Nadav.

Nadav Ofir
  • 778
  • 4
  • 6