Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Save image versions with Refile with streaming as a fallback
class AwsUploader
CLIENT = Aws::S3::Client.new
BUCKET = Rails.configuration.x.aws["output_bucket"]
def self.upload(file, key)
CLIENT.put_object({
bucket: BUCKET,
key: key,
body: file,
content_length: file.size
})
end
def self.delete(key)
resp = CLIENT.list_objects({
bucket: BUCKET,
prefix: key
})
CLIENT.delete_objects({
bucket: BUCKET,
delete: {
objects: resp.contents.map{|c| c.to_hash.slice(:key)}
}
})
end
end
class CacheThumbnailsJob < ActiveJob::Base
queue_as :default
def perform(post)
versions = {}
extension = post.thumbnail_attacher.extension
source_file = Refile.store.get(post.thumbnail_id).download
Post.thumbnails.each do |k, attrs|
filename = "#{k}.#{extension}"
key = [post.thumbnail_prefix, filename].join("/")
file = Refile.processors[attrs[:processor]].call(source_file, attrs[:width], attrs[:height])
AwsUploader.upload(file, key)
versions[k] = filename
end
# thumbnail_versions is an hstore column
post.update(thumbnail_versions: versions)
end
end
class DeleteThumbnailsJob < ActiveJob::Base
queue_as :default
def perform(key)
AwsUploader.delete(key)
end
end
class Post < ActiveRecord::Base
attachment :thumbnail, type: :image
def self.thumbnails
@thumbnails ||= {
md: {
processor: "fill",
width: 480,
height: 270
},
md2x: {
processor: "fill",
width: 960,
height: 540
}
}
end
after_save :cache_thumbnails
def thumbnail_prefix(key=nil)
['thumbnails', (key || thumbnail_id)].join('/')
end
private
def cache_thumbnails
if thumbnail_id_changed?
CacheThumbnailsJob.perform_later(self) if thumbnail_id.present?
DeleteThumbnailsJob.perform_later(thumbnail_prefix(thumbnail_id_was)) if thumbnail_id_was.present?
end
end
end
module PostsHelper
def thumbnail_url(post, version)
filename = post.thumbnail_versions[version.to_s]
if filename.present?
[Rails.configuration.x.cdn_host, post.thumbnail_prefix, filename].join('/')
else
# Fallback to Refile URL if not generated yet
specs = Post.thumbnails[version]
attachment_url(post, :thumbnail, specs[:processor], specs[:width], specs[:height])
end
end
end
@peterfication

This comment has been minimized.

Copy link

peterfication commented May 26, 2016

This looks nice. I will try to adopt it.

But I don't want the jobs to run. I'd rather delete all thumbnails after let's say 30 days and the call to a thumbnail checks if it exists and if not generates it. I don't know if this is possible. What do you think?

@brianlittmann

This comment has been minimized.

Copy link
Owner Author

brianlittmann commented May 26, 2016

You could have a cron job that runs a Rake task which uses the AWS SDK to check if an object exists, and if not generate some thumbnails. In regards to deleting old thumbnails, you'd either need to keep track of the old image hashes/filenames or run some sort of diff on what's in your local database vs. what's listed in S3 and delete anything in S3 that isn't stored locally (which sounds kinda clunky).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.