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!