Search code examples
ruby-on-railsamazon-s3ruby-on-rails-5shrine

Upload images to different folders in s3 (by album names) using Shrine gem


I managed to upload files to s3 using shrine, but I'm trying to upload each photo to a different folder according to the album it belongs to.

Lets say i have a bucket named: abc:

Uploading images to the album: family should upload images to: abc/family/...

Uploading images to the album: friends should upload images to: abc/friends/...

I didn't find a way to do it in Shrine.storages in the initializer file.

I guess the way to do it is with default_storage and dynamic_storage plugins somehow, but i didn't succeed doing it yet.

any suggestions / solution?

Thanks a lot :)

Relations: Album has_many :photos Photo belongs_to :album

Photo class has image_data field for Shrine.

my code in the initializer: (basic stuff)

s3_options = {
  access_key_id:     ENV["S3_KEY"],
  secret_access_key: ENV["S3_SECRET"],
  region:            ENV["S3_REGION"],
  bucket:            ENV["S3_BUCKET"],
}

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
  store: Shrine::Storage::S3.new(prefix: "store", **s3_options),
}

EDIT:

I found out there is a plugin named: pretty_location which adds a nicer folder structure, but its not exactly what i need, it adds /Photo/:photo_id/image/:image_name under the bucket, but i need the album name instead.


Solution

  • I did it!

    by overriding generate_location in the ImageUploader file:

    class ImageUploader < Shrine
      def generate_location(io, context = {})
        album_name  = context[:record].album_name if context[:record].album
        name  = super # the default unique identifier
    
        [album_name, name].compact.join("/")
      end
    end
    

    this will upload the files to: :bucket_name/storage/:album_name/:file_name

    If you want other folder then "storage" you need to change the prefix under the Shrine.storages in the initializer file.

    You might want to use parameterize on the field_name (in my case album_name.parameterize) so you wont have spaces and unwanted characters in the path.

    For anyone out there looking for the answer! thats what worked for me, Enjoy.

    If you have other working/better solution, please post it as well. thanks.