5

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
navi
  • 193
  • 2
  • 12
  • Did you set also ```config.active_storage.service = :amazon``` in ```config/environments/development.rb``` and ```config/environments/production.rb``` files – Semih Arslanoglu Apr 22 '20 at 08:04
  • Consider using `Rails.application.credentials.fetch(:aws).fetch(:access_key_id)` instead of dig which will raise an error if its not present on startup instead of when its used which is very helpful for debugging. – max Apr 22 '20 at 12:40

1 Answers1

4

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
Tom Fast
  • 1,138
  • 9
  • 15
  • as mentioned in a comment to this [answer](https://stackoverflow.com/a/54906011/7573223) it is bad practice to call `send` in this case. `user.photo.service_url.sub(/\?.*/, '')` yields the same result without having to call the service as mentioned in this [other answer](https://stackoverflow.com/a/57822787/7573223) – SMAG Jan 19 '21 at 05:54