Andrew
Andrew

Reputation: 43103

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.

Upvotes: 5

Views: 6637

Answers (2)

Henrik N
Henrik N

Reputation: 16274

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
}

Upvotes: 9

edgarjs
edgarjs

Reputation: 506

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.

Upvotes: 5

Related Questions