Search code examples
ruby-on-railsamazon-web-servicesamazon-s3rails-activestorage

Rails Active Storage & AWS S3 : How to attach image to model through seeds.rb and then store it in S3 private bucket?


For a school project, I'm working on a Rails app which "sells" pics of kittens. I picked 10 pictures of cats online, they are currently on my computer. I'm using Postgresql for the DB. I have a class/model Item which represents the kitten photos.

What I'm looking for is a way to, when generating fake data through seeds.rb loops, attaching a kitten photo to each Item class/model, which will be then stored to an AWS S3 bucket that is already created (it's called catz-temple). I have my two access and secret S3 keys on a .env file, I already have modified my storage.yml file like so :

amazon:
    service: S3
    access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
    secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
    region: eu-central-1
    bucket: catz-temple

I found out there was a gem called aws-sdk-ruby, but I just can't find out what approach I should have on this topic.

For now, I just put my bucket in public access and take each bucket photos' urls, but there's no API and secure approach into this...

Thank you all


Solution

  • Starting by follow the guides for configuring ActiveStorage and S3. Then setup the attachments on your model.

    class Kitteh < ApplicationRecord
      has_one_attached :photo
    end
    

    With ActiveStorage you can directly attach files to records by passing an IO object:

    photos = Rails.root.join('path/to/the/images', '*.{jpg,gif,png}')
    100.times do |n|
      path = photos.sample
      File.open(path) do |file|
        Kitteh.new(name: "Kitteh #{n}") do |k|
          k.photo.attach(
            io: file,
            filename: path.basename 
          )
        end.save!
      end
    end
    

    This example creates 100 records with a random image selected from a directory on your hard drive and will upload it to the storage you have configured.