navi
navi

Reputation: 193

Can't retrieve file from S3 with Rails Active Storage

I am trying to upload a photo to S3 using Rails Active Storage.

I can attach a photo:

user.photo.attach(io: File.open('spec/images/filename.png'), filename: 'filename.png')

I can save the user and I can get the photo service url and see it in the browser, and in my bucket:

user.photo.service_url

However, if I restart my console and try to get the service url, I receive the following error:

Module::DelegationError (service_url delegated to attachment, but attachment is nil)

Here are my bucket settings:

storage.yml:

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-2
  bucket: <%= Rails.application.credentials.dig(:aws, :bucket) %>

application.rb:

config.active_storage.service = :amazon

user.rb:

has_one_attached :photo

I am also having trouble using public: true in the storage.yml file.

I receive the following error if I try to set the config:

ArgumentError (Cannot load `Rails.config.active_storage.service`:)
invalid configuration option `:public'
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-2
  bucket: <%= Rails.application.credentials.dig(:aws, :bucket) %>
  public: true

Upvotes: 5

Views: 2025

Answers (1)

Tom Fast
Tom Fast

Reputation: 1158

I also wanted to upload my files to AWS S3, and have them publically available.

I ran into this issue as well and found the following:

ArgumentError (Cannot load `Rails.config.active_storage.service`:)
invalid configuration option `:public'

comes from this file in the aws-sdk-ruby gem. As per the error message, the aws-sdk-ruby gem does not support the public: true option.

I used the following work-around (special thanks to this article):

  1. I updated my storage.yml to:
public_amazon:
  service: S3
  access_key_id: some_key
  secret_access_key: some_secret
  bucket: some-bucket-name
  region: some-region
  upload:
    acl: "public-read"

The above sets the uploaded file permissions to be public.

  1. Retrieve the public URL like this:
user.photo.attach(params[:file])
url = user.photo.service.send(:object_for, user.photo.key).public_url

Upvotes: 5

Related Questions