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
开发者_StackOverflow 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.
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
}
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.
精彩评论