Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Carrierwave recreate versions does not change old images

My Rails app uses carrierwave to manage image uploads. I have a watermark version of the images on my site. Previously I was overlaying an image on them, like so:

def watermark
    manipulate! do |img|
        logo = Magick::Image.read("#{Rails.root}/public/images/plc-watermark.png").first
        img = img.composite(logo, Magick::SouthEastGravity, Magick::OverCompositeOp)
    end
end

Now I'm overlaying text, like so:

def watermark
    manipulate! do |img|
        text = Magick::Draw.new
        text.gravity = Magick::CenterGravity
        text.pointsize = 12
        text.font = "#{Rails.root}/public/fonts/hn300.ttf"
        text.stroke = 'none'
        text.annotate(img, 0, 0, 0, 0, "Photo © #{model.user.full_name}\nHosted by Placeology.ws\nPlease log in to remove this watermark")
        img
    end
end

Now, this works for new images, but when I call recreate_versions! the old photos are not replaced. How can I get this new watermark to replace the old one?

For what it's worth I'm using Fog with Amazon S3 for storage in both development and production.

like image 893
Andrew Avatar asked Aug 25 '11 18:08

Andrew


2 Answers

This might not be quite the same issue, but for googleability:

We have a random hash in the filename similar to what is described in this discussion thread.

When regenerating images, it would generate new images, using a new hash, but it wouldn't update the filename stored in the database, so it would attempt to display images with the old names.

This reproduces the problem:

bundle exec rails runner "Foo.find(123).images.each { |img| uploader = img.image; puts %{before: #{img.image.inspect}}; uploader.recreate_versions!; puts %{after: #{img.reload.image.inspect}} }; p Foo.find(123).images"

It gives output like

before: /uploads/foo_123_6a34e47ef5.JPG
after: /uploads/foo_123_d9a346292d.JPG
[#<Image id: 456, foo_id: 123, image: "foo_123_6a34e47ef5.JPG">]

But adding a img.save! after recreating versions fixes it:

bundle exec rails runner "Foo.find(123).images.each { |img| uploader = img.image; puts %{before: #{img.image.inspect}}; uploader.recreate_versions!; img.save!; puts %{after: #{img.reload.image.inspect}} }; p Foo.find(123).images"

With output:

before: /uploads/foo_123_6a34e47ef5.JPG
after: /uploads/foo_123_d9a346292d.JPG
[#<Image id: 456, foo_id: 123, image: "foo_123_d9a346292d.JPG">]

Edit:

Actually, the above worked with files on disk, but not with fog. To make things easy for myself, I ended up just recreating the images and removing the old ones:

Image.all.each { |old|
  new = Image.new(foo_id: old.foo_id, image: old.image)
  new.save!
  old.destroy
}
like image 109
Henrik N Avatar answered Nov 09 '22 19:11

Henrik N


You need to call image.cache_stored_file! before calling recreate_versions!

It's weird because the method itself calls that if the file is cached, but for some reason it wasn't working.

like image 5
edgarjs Avatar answered Nov 09 '22 18:11

edgarjs