Paperclip, S3 & Delayed Job in Rails
Here’s how I use Paperclip (with storage on S3) and delayed_job to process images after they’re uploaded in the background. This means users don’t have to wait while the images are resized to the versions you’ve specified in Paperclip’s :style option.
Assumes you have Paperclip configured using S3 for an existing model (Image in this example) and delayed_job installed (as plugin or gem) with the required table created.
Add a :processing flag to our model:
class AddProcessingToImages < ActiveRecord::Migration
def self.up
add_column :images, :processing, :boolean
end
def self.down
remove_column :images, :processing
end
end
Then, in our model:
class Image
# define our paperclip attachment
has_attached_file :source ...
...
# cancel post-processing now, and set flag...
before_source_post_process do |image|
if image.source_changed?
image.processing = true
false # halts processing
end
end
# ...and perform after save in background
after_save do |image|
if image.source_changed?
Delayed::Job.enqueue ImageJob.new(image.id)
end
end
# generate styles (downloads original first)
def regenerate_styles!
self.source.reprocess!
self.processing = false
self.save(false)
end
# detect if our source file has changed
def source_changed?
self.source_file_size_changed? ||
self.source_file_name_changed? ||
self.source_content_type_changed? ||
self.source_updated_at_changed?
end
...
end
Create a job wrapper, which used by DelayedJob:
class ImageJob < Struct.new(:image_id)
def perform
Image.find(self.image_id).regenerate_styles!
end
end
Thanks to this article which helped a lot.