How to use Delayed Job to handle your Carrierwave processing
This tutorial builds on my previous post about how to add FFMPEG processing to Carrierwave. Here I will show you my attempt at being able to utilize Delayed::Job to do the heavy lifting of processing when uploading files using Carrierwave. Remember, this could probably use some improvement, but it is a great starting point. So lets begin. The first thing you will need to do is add Delayed::Job to your application:
# Gemfile gem "delayed_job"
Next you need to create the migration and migrate the database:
rails generate delayed_job rake db:migrate
Now we get to the good part. Lets create a module to include into Carrierwave that will support holding off on doing the processing until Delayed::Job gets around to it:
# lib/carrier_wave/delayed_job.rb module CarrierWave module Delayed module Job module ActiveRecordInterface def delay_carrierwave @delay_carrierwave ||= true end def delay_carrierwave=(delay) @delay_carrierwave = delay end def perform asset_name = self.class.uploader_options.keys.first self.send(asset_name).versions.each_pair do |key, value| value.process_without_delay! end end private def enqueue ::Delayed::Job.enqueue self end end def self.included(base) base.extend ClassMethods end module ClassMethods def self.extended(base) base.send(:include, InstanceMethods) base.alias_method_chain :process!, :delay ::ActiveRecord::Base.send( :include, CarrierWave::Delayed::Job::ActiveRecordInterface ) end module InstanceMethods def process_with_delay!(new_file) process_without_delay!(new_file) unless model.delay_carrierwave end end end end end end
Awesome! Now we need to tie this into our Uploader:
# app/uploaders/asset_uploader.rb require File.join(Rails.root, "lib", "carrier_wave", "ffmpeg") require File.join(Rails.root, "lib", "carrier_wave", "delayed_job") # New class AssetUploader < CarrierWave::Uploader::Base include CarrierWave::Delayed::Job # New include CarrierWave::FFMPEG # Choose what kind of storage to use for this uploader: storage :file # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "#{Rails.root}/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end # Add a version, utilizing our processor version :bitrate_128k do process :resample => "128k" end end
The last thing we have to do is update our model to queue up delayed job:
# app/models/asset.rb class Asset < ActiveRecord::Base mount_uploader :asset, AssetUploader after_save :enqueue # New end
There you have it. Now when you create a new Asset, associate a file, and save it, it shouldn’t run the processes, but instead create a Delayed::Job record. Then Delayed::Job should pick it up and run the processors on it. This may not be perfect, but at least its a start! Thanks for reading!