Rails Active Storage: how to access file contents before it has been saved

3,034 views
Skip to first unread message

Nerdture

unread,
Dec 4, 2019, 8:05:50 AM12/4/19
to Ruby on Rails: Core
I am working on building an API front end for a 3rd Party API.  In addition to collecting the file from my user, I also need to post the file to the 3rd Party Service.

The only way I have been able to get the actual file contents is to download it again after it has been saved.

class Template < ApplicationRecord
    has_one_attached
:pv_file
...
    post_body
<< self.pv_file.blob.download

I want to have a before create filter that throws an error if the 3rd Party API rejects the file (e.g. wrong format, service unavailable, etc), but the only way I have found to access the file content is by downloading it again.

How can we access the actual file content before it has been saved and uploaded?

Mladen Ilic

unread,
Dec 4, 2019, 9:05:44 AM12/4/19
to Ruby on Rails: Core
Hi Nerdture,

I'm not a core team member, but I believe that there's currently no documented way of accessing a file before the record has been saved (more precisely, before the after_commit callback). There is, however, `attachment_changes` hash, which keeps track of what changes are made. You should be able to access the attachment with `record.attachment_changes['pv_file']`. Keep in mind that this is undocumented internal api, so it could change in the future.

Nerdture

unread,
Dec 4, 2019, 1:53:03 PM12/4/19
to Ruby on Rails: Core
Thanks Mladen Ilic for your reply.  

I think I am getting closer to the solution I need.


You should be able to access the attachment with `record.attachment_changes['pv_file']`. 

I must be doing something wrong, as I can't figure out how to access the actual file contents/octet-stream.

post_body << self.attachment_changes['pv_file']
throws Zlib::Data Error incorrect header check

post_body << self.attachment_changes['pv_file'].blob.download
throws Aws::S3::Errors::NoSuchKey

post_body << self.attachment_changes['pv_file'].blob.open
throws ActiveStorage::FileNotFoundError

I am sure I am showing my Ruby ignorance here.

Any help is appriciated.

Mladen Ilic

unread,
Dec 5, 2019, 9:07:07 AM12/5/19
to Ruby on Rails: Core
Hi again Nerdture,

According to the implementation of ActiveStorage::Attached::Changes::CreateOne, you should be able to access instance of ActionDispatch::Http::UploadedFile with following:
self.attachment_changes['pv_file'].attachable

In you examples, you are trying to download file from a storage service to a tempfile before it has been uploaded, so storage service fails to locate it.

Best,

Nerdture

unread,
Dec 9, 2019, 8:07:57 AM12/9/19
to Ruby on Rails: Core
Thanks again Mladen Ilic for your help.

For anyone that finds this, in order to build the multipart form-data, I needed to use the following to get the Octet-stream.

post_body << self.attachment_changes['pv_file'].attachable.read

Hopefully we will eventually get a permanent/documented way to access the data pre-save.


Reply all
Reply to author
Forward
0 new messages