Skip to content

Instantly share code, notes, and snippets.

@bassemawhoob
Created November 17, 2022 10:55
Show Gist options
  • Save bassemawhoob/f0356faaafa239e085fbecc5ffe73dfd to your computer and use it in GitHub Desktop.
Save bassemawhoob/f0356faaafa239e085fbecc5ffe73dfd to your computer and use it in GitHub Desktop.
Production S3 to local ActiveStorage on Rails
# Reference: https://dev.to/lucaskuhn/syncing-files-from-aws-s3-to-local-storage-on-rails-3639
# Main goal: Sync a specific model's S3 images locally to have productions images working in development
# Assuming I have a model called `ProductImage` with an attachment called `artwork`
s3_bucket = "YOUR_S3_BUCKET"
access_key_id = Rails.application.credentials.dig(:aws, :access_key_id)
secret_access_key = Rails.application.credentials.dig(:aws, :secret_access_key)
storage_folder = Rails.root.join('storage')
storage_folder.mkpath
# For a specific model run the following loop or if you want to sync everything on S3 you can just run
# system("AWS_ACCESS_KEY_ID=#{access_key_id} AWS_SECRET_ACCESS_KEY=#{secret_access_key} aws s3 sync s3://#{s3_bucket} #{storage_folder}")
# instead of the loop
ProductImage.find_each do |product_image|
key = product_image.artwork.blob.key
system("AWS_ACCESS_KEY_ID=#{access_key_id} AWS_SECRET_ACCESS_KEY=#{secret_access_key} aws s3 sync s3://#{s3_bucket}/#{key} #{storage_folder}")
end
# Ignores sub_folders already created and .keep files
images = storage_folder.children.select { |file| file.file? && !file.empty? }
# Formats the file path of each image so ActiveStorage understands them using :local storage
images.each do |path_name|
dir, basename = path_name.split
file_name = basename.to_s
sub_folders = dir.join(file_name[0..1], file_name[2..3])
sub_folders.mkpath # Create the subfolder used by active_record
path_name.rename(dir + sub_folders + basename) # Renames file to be moved into subfolder
end
# If we dumped the production data & restored it locally, all blobs will have a service_name `amazon`.
# We need to change this service name to `local` for rails to know where to fetch the blob from
ActiveStorage::Blob.update_all(service_name: "local")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment