how to serve thumbnail version of default image with carrierwave - ruby-on-rails

My default image is working with carrierwave, except I can't get a thumb version of the default. #profile.photo and #profile.photo.thumb both return the same default_profile.png. How do I get this to work
Also, when I do upload a photo, #profile.photo.thumb does correctly return the resized version of the uploaded photo.
In /assets/images:
I have default_profile.png and thumb_default_profile.png, the latter is, of course, a scaled down version of the former. I also tried renaming the thumb file to default_profile_thumb.png
relevant portion of profile_photo_uploader.rb:
def default_url
"default_profile.png"
end
version :thumb do
process :resize_to_fill => [60, 60]
end

def default_url
"default_profile.png"
end
version :thumb do
process :resize_to_fill => [60, 60]
def default_url
"thumb_default_profile.png"
end
end

Nicer way todo:
def default_url(*args)
ActionController::Base.helpers.asset_path([version_name, "default_profile.png"].compact.join('_'))
end

Related

Carrierwave: Move version name to end of filename, instead of front

Currently with Carrierwave, after uploading a file like foo.png when creating different versions like so:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :fog
def store_dir
"#{model.class.to_s.underscore}/#{model.id}"
end
version :thumb do
process :resize_to_fit => [500, 500]
end
end
that results in the files being uploaded as:
thumb_foo.png
foo.png
I want to move "thumb" to the end of the filename for SEO reasons. Based on their docs here I added:
def full_filename(for_file)
if parent_name = super(for_file)
extension = File.extname(parent_name)
base_name = parent_name.chomp(extension)
[base_name, version_name].compact.join("_") + extension
end
end
def full_original_filename
parent_name = super
extension = File.extname(parent_name)
base_name = parent_name.chomp(extension)
[base_name, version_name].compact.join("_") + extension
end
The docs say this should result in:
foo_thumb.png
foo.png
However, I end up actually getting the following:
thumb_foo_thumb.png
foo.png
Any idea what I'm doing wrong?
Simply use #full_filename under the version block:
class AvatarUploaer < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
version :thumb do
process resize_to_fill: [50, 50]
def full_filename(for_file = model.logo.file)
parts = for_file.split('.')
extension = parts[-1]
name = parts[0...-1].join('.')
"#{name}_#{version_name}.#{extension}"
end
end
end
The result will be following:
/Users/user/app/uploads/1x1.gif
/Users/user/app/uploads/1x1_thumb.gif
More information in Wiki: How to: Migrate from one model to another
MVP example: https://gist.github.com/itsNikolay/2394f84f31db33d4c3dc6634068b0259
If you have a lot of versions, the accepted answer can get a little tedious.
I ended up overriding full_filename for everything instead of in each individual version definition. It works fine. This is for Carrierwave 1.0
photo_uploader.rb
# Override the filename of the uploaded files:
def full_filename(name)
"#{File.basename(name, '.*')}_#{version_name || 'original'}#{File.extname(name)}"
end
I'm using the built in File.basename and File.extname methods instead of doing it manually as seen in the accepted answer (although that's where I started and that code works fine too).
Note: I wanted to add "original" to the unversioned upload just so my directory listing looked cleaner. That part could be removed fairly easily.
foo_mobile.jpg
foo_original.jpg
foo_square.jpg
In the current version of CarrierWave if you have an uploader defined like this:
class LogoUploader < CarrierWave::Uploader::Base
# ...
def filename
"original_#{model.logo.file.extension}" if original_filename
end
version :small do
process :resize_to_fit => [190, 190]
process :convert => 'png'
end
version :icon do
process :resize_to_fill => [50, 50]
process :convert => 'png'
end
# ...
end
and attach a file name somefile.jpg, you will end up with files named original.jpg, original_small.png and original_icon.png respectively.

How can I make 2 uploader to point to 1 cloudinary file when using carrierwave?

I have Image model:
class Image < ActiveRecord::Base
mount_uploader :file, ModuleImageUploader
end
To upload image I use carrierwave + cloudinary:
class ModuleImageUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
process :resize_to_limit => [700, 700]
version :mini do
process :resize_and_pad => [50, 50, '#ffffff']
end
version :thumb do
process :resize_and_pad => [100, 100, '#ffffff']
end
def public_id
return SecureRandom.uuid
end
end
I created new model AccountMediaContent:
class AccountMediaContent < ActiveRecord::Base
mount_uploader :image, AccountMediaContentImageUploader
end
with it's uploader which also uses carrierwave:
class AccountMediaContentImageUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
process :resize_to_limit => [700, 700]
version :mini do
process :resize_and_pad => [50, 50, '#ffffff']
end
version :thumb do
process :resize_and_pad => [100, 100, '#ffffff']
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
Right now I need to the way to transfer the image from Image to AccountMediaContent. So, that means if I had such file in Image:
http://res.cloudinary.com/isdfldg/image/upload/v1344344359/4adcda41-49c0-4b01-9f3e-6b3e817d0e4e.jpg
Then it means that I need the exact same file in AccountMediaContent so the link to the file will be the same. Is there any way to achieve this?
The optimal solution for this would be to have a new model which represents the image, and then link it to both models.
Ok my solution is not really good but anyway. What I did is I wrote the script which downloaded already existing images Image in Cloudinary and then I attached them to new model AccountMediaContent.
My task looks like this:
Image.find_in_batches do |imgs_in_batch|
imgs_in_batch.each do |img|
# Downloading image to tmp folder (works on heroku too)
file_format = img.file.format
img_url = img.file.url
tmp_file = "#{Rails.root.join('tmp')}/tmp-img.#{file_format}"
File.open(tmp_file, 'wb') do |fo|
fo.write open(img_url).read
end
# Creating AccountMediaContent with old image (it'll be uploaded to cloudinary.
AccountMediaContent.create(image: File.open(tmp_file))
FileUtils.rm(tmp_file)
end
end
Hope it'll be useful for someone.

Carrierwave store original file after creating the version

I have ImageUploader class and i want to save my original image with original size of the image after saving the particular version. Help me to solve this
Uploader
class ImageUploader < IconBase
process :resize_to_fill => [490,68]
version :normal do
process resize_to_fill: [245,34]
def full_filename(for_file = model.logo.file)
"avatar1.png"
end
end
def filename
"avatar.png"
end
end
Your original size is not saved, because you have process :resize_to_fill => [490,68] in your uploader. To keep original size, you can put this into another version, so your main image will stay unproccessed, like this:
version :large do
process :resize_to_fill => [490,68]
end
Then you'll have:
uploader.url # original image
uploader.large.url # [490,68] version
uploader.normal.url # [245,34] version

Rails + Carrierwave + RMagick: GIF converts to JPG but doesn't save right file extension

I'm currently trying to get the first frame of a gif file, resize it and save it as a jpg file.
The conversion seems fine I think. But it doesn't save it with the right file extension. It still gets saved as .gif
So when I try to open it it says can't open image, doesn't seem to be a GIF file. Then I rename the extension myself and it works.
Here is my processing code:
version :gif_preview, :if => :is_gif? do
process :remove_animation
process :resize_to_fill => [555, 2000]
process :convert => 'jpg'
end
def remove_animation
manipulate! do |img, index|
index == 0 ? img : nil
end
end
There is actually another, cleaner way to achieve this; and it is even somewhat documented in the official wiki: How To: Move version name to end of filename, instead of front
Using this method your version code would look like this:
version :gif_preview, :if => :is_gif? do
process :remove_animation
process :resize_to_fill => [555, 2000]
process :convert => 'jpg'
def full_filename(for_file)
super.chomp(File.extname(super)) + '.jpg'
end
end
def remove_animation
manipulate! do |img, index|
index == 0 ? img : nil
end
end
So ... I finally found a solution after hours of headaches why this didn't work. Turns out you have to touch/create a file first in order to make this work. I also switched from RMagick to Mini Magick. Not for a particular reason just tried it out if it would work with MiniMagick but I still had the same problem. Here is my new process code with Mini Magick:
version :gif_preview, :if => :is_gif? do
process :gif_to_jpg_convert
end
def gif_to_jpg_convert
image = MiniMagick::Image.open(current_path)
image.collapse! #get first gif frame
image.format "jpg"
File.write("public/#{store_dir}/gif_preview.jpg", "") #"touch" file
image.write "public/#{store_dir}/gif_preview.jpg"
end
I just don't understand why there is really 0 documenation about this ...

Having trouble getting multiple carrierwave processes to run

I am attempting to optimize images when resizing them with Carrierwave but haven't had any luck getting this to work. Carrierwave is generating the different sized versions, but my custom optimize and the convert processes aren't running. I've tried calling the different processes in different places, but nothing seems to work.
Any ideas on what I might be doing wrong? Could it be the same issue here: CarrierWave RMagick - How do I cause manipulate! to be called?
class FooUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
# Attempt #1
process :convert => 'jpg'
process :optimize
version :meow do
process :resize_to_fill => [700, 400]
end
# Attempt #2
version :meow do
process :convert => 'jpg', :optimize => nil, :resize_to_fill => [700, 400]
end
# Attempt #3
version :meow do
process :resize_to_limit => [700, 400]
process :optimize
process :convert => 'jpg'
end
# Attempt #4
# Tried switching order around since they are being resized but not converted
version :meow do
process :convert => 'jpg'
process :optimize
process :resize_to_limit => [700, 400]
end
# Optimize method used by all versions
def optimize
manipulate! do |img|
img.strip
img.combine_options do |c|
c.quality "96"
c.depth "24"
c.interlace "plane"
#c.interlace "Plane" # Tried both cases, seen examples of both
end
img
end
end
end
Well that not entirely possible they way you want if you are using carrierwave mini-magick or rmagick helper method
Solution 1)
if you get rid of carrierwave helper then perhaps it can work
do something like this
process :custom_processing
def custom_processing
// You have to write you own code for and not CarrierWave helper method to achieve this
// write your own code to convert to jpg
// write your code to optimize
// write your code to resize from the converted n optimize image
end
this way you do all your processing in one shot ,having said but you have to dig in mini_magick/rmagick documentation to know how what method to call for each as you cant rely on carrierwave helper (since they are registered/called via process method and one cannot call call/invoke process inside process )
so something like this you can't achieve
def custom_processing
process :convert => 'jpg'
process :optimize
process :resize_to_fit => [700, 400]
end
Solution 2)
With Carrierwave Helper but through multiple versions you can eventually achieve this
version :jpg do
process :convert => 'jpg'
end
version :optimize_jpg ,:from => :jpg do
process :optimize
end
version :meow,:from => :optimize_jpg do
process :resize_to_limit => [700, 400]
end
More reference of this can be found here
Now this approach take care of headache of Approach 1 digging to documentation(since we are using Carrierwave helper methods), but as you can see you have to create multiple versions to achieve this
Question : Why Multiple version ?
Well that how it Carrierwave work it create a uploader for each version and if from options isnt applied it consider the original images (uploaded images) as the source file(parent file) create the desired version

Resources