cpg
1/16/2012 - 9:24 PM

process paperclip attachments in the background

process paperclip attachments in the background

# == Schema Information
#  you need to add a flag to the model to indicate his processing status
#  it defaults to true:
#
#  attachment_processing     :boolean(1)      default(TRUE)
#  ...
#
#----------------------------------------------------------------------

class Thing < ActiveRecord::Base

  # this is the full paperclip configuration, including thumbnail generation
  # and s3 uploads, the idea is to execute all this in the background.
  has_attached_file :attachment,
    styles: {
      square_icon:  "48x48#",
      square_thumb: "150x150#",
      big:          "650x650>"
    },
    path: ":id_partition/:random_key_:style.:extension",
    s3_credentials: {
      access_key_id: AMAZON_ACCESS_KEY,
      secret_access_key: AMAZON_SECRET_KEY
    },
    bucket: BUCKET_NAME,
    storage: :s3

  # after_attachment_post_process  :post_process_attachment

  # def post_process_attachment
  #   ...
  # end
end


# temp model
#----------------------------------------------------------------------

class TempThing < Thing

  has_attached_file :attachment,
    path: ":rails_root/public/system/temp_attachments/:basename.:extension"

  after_save :process_in_background

  def process_in_background
    # I use Resque as the job queue, you can use whatever you want
    Resque.enqueue(Jobs::PostProcessThing, self.id)
  end

end

# the idea is to use the TempThing model to create a new Thing, this way only the paperclip
# options specified in the TempThing model will be applied, only the original file will be saved
# and the slow thumb generation and s3 uploads will not be executed.
#
# In the Things controller:

def new
  @thing = TempThing.new
end

# use the @thing model as usual in the views, just add your multipart form

# Just after the TempThing gets saved, a Job will be queued to be executed later in the background.
#
# In the background job you can do something like this:

temp_thing = TempThing.find(temp_thing_id)
thing = Thing.find(temp_thing_id) # temp_thing and thing are the same record
# the attachment is updated AND processed usng the paperclip config in the Thing model
thing.attachment = temp_thing.attachment.to_file
# we update the processing flag so we can know that the Thing is already processed
thing.attachment_processing = false
thing.save!
path = temp_thing.attachment.path
temp_thing.attachment.to_file.close
File.delete(path) # we can delete the temp attachment now

# in the views you can inmediately display a new uploaded attachment, and since you know
# that the Thing is being processed you can display a "processing" thumb or something like that