Skip to content

Instantly share code, notes, and snippets.

@catmando
Last active September 27, 2017 07:13
Show Gist options
  • Save catmando/096c29d0fb06873ad978 to your computer and use it in GitHub Desktop.
Save catmando/096c29d0fb06873ad978 to your computer and use it in GitHub Desktop.
Carrierwave Custom Version
class CustomUploader < CarrierWave::Uploader::Base
# complete example of custom carrierwave version generator that does not use manipulate with hopefully helpful comments
# in this case we are uploading a .psd (photoshop file) and then rendering to a png. We want to
# save the original psd, so we create a png version.
storage :file
version :png do # tells carrierwave to generate a new version of the upload in this case a "png"
# step one: generate the png
process :generate_custom_png
# optional step two: rename the file name from something like "png_xxx.psd" to "xxx.png"
# note that for version :zzz you would change all references to from png to zzz
# by putting full_filename inside the version block this seems to only modify the behavior for this specific version
def full_filename(for_file)
super.chomp(File.extname(super)).gsub('png_','') + '.png'
end
end
def generate_custom_png
# when this method is called current_path is pointing to a copy
# of the original file
# the methods job is to rewrite the file to whatever the new version should be
# in this case its easy, but sometimes the underlying conversion process
# needs to seperate input and output files.
# In that case first mv the file to a new file with same name plus ".tmp" on the end
# process that file, with the output going to the "current_path" file.
puts "converting #{original_filename} to #{current_path}" # note that the file names will still be messed up at this point
# in this example we are using the PSD gem to read a PSD file and turn it into a PNG.
PSD.open(current_path) do |f|
begin
f.tree.save_as_png(current_path)
rescue Exception => e
# this optional but shows how I handle any errors arising during the conversion.
# in this case the model has a processing_errors string that we concat the error message onto
model.processing_errors =
[model.processing_errors, "Could not generate background png: #{e.message}"].compact.join("/n")
end
end
end
end
@catmando
Copy link
Author

I really struggled to understand carrierwave's "version" creation process. All the examples use "manipulate" and its not clear how everything really works.

The secret that I did not understand was that when the processing method is called "current_path" is pointing to a a new copy of the temp file, already loaded with the previous processing steps output.

So the processing method just needs to read the file pointed to by "current_path", process it however it wants and then write it back out to "current_path".

Once you get it, it makes perfect sense. For example if the processing method does nothing then essentially you have created a copy of the input file.

One additional thing that confused me, was that the one example I did find was overly complicated because the process being used to generate the new output needed to have the input file open while writing the output file. So in this case the processing method has to first copy current_path to a new temp file (just adding .tmp on the end should work fine) so that the process output can be dumped back into current_path

Hope this helps somebody

@mvaragnat
Copy link

Thank you - very useful

@moizhb
Copy link

moizhb commented Sep 27, 2017

Thank you. I struggled exactly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment