Skip to content

Instantly share code, notes, and snippets.

@fareesh
Created January 27, 2014 01:33
Show Gist options
  • Save fareesh/8641981 to your computer and use it in GitHub Desktop.
Save fareesh/8641981 to your computer and use it in GitHub Desktop.
Use AWS-SDK to Migrate Paperclip Attachments from Files to S3
# Create config/s3.yml
# Example:
# development:
# bucket: electric-images
# access_key_id: AKIAJADQBJZ4GTP4FY7A
# secret_access_key: CKu9iYpFZoLRfr9zadtDRUA3BYUUWmnghyy2AJrg
# region: ap-southeast-1 #Change this
namespace :attachments do
desc "migrate files from filesystem to s3"
task :migrate_to_s3 => :environment do
require 'aws/s3'
# Load credentials
s3_options = YAML.load_file(File.join(Rails.root, 'config/s3.yml'))[Rails.env].symbolize_keys
bucket = s3_options[:bucket]
# Establish S3 connection
s3_options.delete(:bucket)
s3 = AWS::S3.new(:access_key_id => s3_options[:access_key_id], :secret_access_key => s3_options[:secret_access_key], :region => s3_options[:region])
#AWS::S3::Base.establish_connection!(s3_options)
# determine the models to migrate
klasses = ["Spree::Image"]
klasses.each do |klass_sym|
if @klass = real_klass(klass_sym)
if @klass.respond_to?(:attachment_definitions) && definitions = @klass.attachment_definitions
total_items = @klass.count
current_item = 1
@klass.all.each do |record|
definitions.each_pair do |column, value|
attachment = record.send(column.to_sym)
# NOTE: If the application is configured to use S3 already,
# calling exists? won't work as expected because paperclip will automatically look on Amazon.
if !attachment.exists?
total_items -= 1
next
end
styles = value[:styles].keys rescue []
styles.push(:original)
styles.each do |style|
# whatever mapping needed to where your files will live on S3
# in my case, I changed the URL when migrating to S3
path = attachment.url(style.to_sym).gsub('/system/files', '') #Change this to whatever is relevant to your paths
file = attachment.path(style.to_sym)
# skip if we already have this file on S3
#next if AWS::S3::S3Object.exists?(path, bucket)
next if s3.buckets[bucket].objects[path].exists?
begin
print "uploading: #{style.to_sym}..."
s3.buckets["electric-images"].objects[path].write(:file => file)
#AWS::S3::S3Object.store(path, file, bucket, :access => :public_read)
print " done.\n"
rescue Exception => e
puts e.inspect
end
end
# fancy output
percent_complete = ((current_item.to_f / total_items.to_f) * 100).round(2)
puts "Completed: #{current_item} / #{total_items}: ~#{percent_complete}%"
current_item += 1
end
end
else
puts "There are no paperclip attachments defined for: #{@klass.to_s}"
end
else
puts "#{klass_sym.to_s.classify} is not an existing model."
end
end
end
def real_klass(key)
key.to_s.classify.constantize
rescue
end
end
@fareesh
Copy link
Author

fareesh commented Jan 27, 2014

Run with rake attachments:migrate_to_s3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment