I've ran into this same problem a few times. The way I solved it was by creating 2 models, a Image
model and a TempImage
model, which inherits from the Image
model. This requires you to have a type
column on your Image
table. The TempImage
model saves the image locally, then when you access it from the Image
model directly and resave it, it will follow whatever is defined in the Image
model, being Amazon S3.
Example:
# Will save in the database as a TempImage inside the Image table
temp = TempImage.create(:asset => File.new('some_path', 'r'))
# When you find it again through the Image model, it bypasses the type column
# so next time you save it, it is saved as an Image.
amazon = Image.find(temp.id)
amazon.save!
Here is my delayed job:
class MoveToS3Job < Struct.new(:temp_revision_id)
def perform
upload = Image.find(temp_revision_id)
temp_path = File.expand_path("tmp/uploads/#{upload.asset_file_name}", Rails.root)
upload.asset = File.new(temp_path, 'r')
upload.save!
if File.exists?(temp_path) && !File.directory?(temp_path)
File.delete(temp_path)
end
rescue ActiveRecord::RecordNotFound
# If the record wasn't found, do some sort of
# error report, but don't keep it in the queue.
end
end
Here is the TempImage
model:
class TempImage < Image
has_attached_file :asset, {
:path => ":rails_root/tmp/uploads/:basename_:updated_at.:extension"
}
end
Then the original Image
model:
class Image < ActiveRecord::Base
# Validations
validates :asset, :presence => true
# Paperclip
has_attached_file :asset, :styles => {
:preview => ['100x100#', :png],
:thumb => ['50x50#', :png]
},
:default_style => :thumb,
:storage => :s3,
:bucket => 'bucket-name',
:s3_credentials => File.expand_path('config/s3.yml', Rails.root),
:path => "photos/:id_partition/:style.:extension"
end
Your original Image
model should always contain your post processing, as that will be done in the background.
You can always overwrite some methods to make it a little cleaner, but this gives you a better idea of how it works and what you need to do to so you can have it work like you want it to.