Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CarrierWave with ActiveResource

Does anyone have any insights into using CarrierWave with an ActiveResource model (in Rails 3)? I've got an ActiveResource model with field for the filename, and I want to save the file to the remote filesystem.

I've tried a few things without much success (or conviction that I was doing anything remotely correctly), so I'd appreciate suggestions from anyone who's successfully implemented CarrierWave without using the ORM modules already included in the gem.

like image 765
tmo256 Avatar asked Jan 21 '23 07:01

tmo256


1 Answers

I'm probably late for this as the original author has moved on, but this question comes up at the top when someone searches for "carrierwave activeresource", so I thought it was still worth answering.

For the sake of discussion, let's assume we have a model named Artist with a picture named artist_picture mounted as a CarrierWave uploader. With ActiveRecord, you would assign this picture to a File:

artist.artist_picture=File.open('ravello.jpg')

And when you save artist:

artist.save!

the picture will be saved, also.

Now, let's say I create a resource based on this:

class Artist < ActiveResource::Base
end

If I subsequently read in an artist:

artist = Artist.find(1)

and look at it, I'll find this in there:

#<Artist:0x39432039 @attributes={"id"=>1, "name"=>"Ravello", "artist_picture"=>#<ArtistPicture:0x282347249243 @attributes={"url"=>"/uploads/artists/artist_picture/1/ravello.jpg"}, @prefix_options={}, @persisted=false>, @prefix_options={}, @persisted=false>

Interestingly, artist_picture is itself a model and we could declare it and play around with it if we wanted. As it is, you can use the url to grab the picture if you want. But let's talk instead about uploading another picture.

We can add this little bit of code to the Artist model on the server side:

  def artist_picture_as_base64=(picsource)
    tmpfile = Tempfile.new(['artist','.jpg'], Rails.root.join('tmp'), :encoding => 'BINARY')
    begin
      tmpfile.write(Base64.decode64(picsource.force_encoding("BINARY")))
      file = CarrierWave::SanitizedFile.new(tmpfile)
      file.content_type = 'image/jpg'
      self.artist_picture = file
    ensure
      tmpfile.close!
    end
  end

I'm just showing a simple example - you should probably pass the original filename, also. Anyway, on the resource side:

class Artist < ActiveResource::Base
  def artist_picture=(filename)
    self.artist_picture_as_base64=Base64.encode64(File.read(filename))
  end
end

At this point, on the resource side you need only set "artist_picture" to a filename and it will be encoded and sent when the resource is saved. On the server side, the file will be decoded and saved. Presumably you could skip base64 encoding by just forcing the string to binary encoding, but it craps when I do that and I don't have the patience to track it down. Encoding as base64 works.

like image 77
Michael Chaney Avatar answered Feb 06 '23 09:02

Michael Chaney