Rails 6 adds ActiveStorage::Blob#open

Akhil Gautam

By Akhil Gautam

on October 30, 2019

This blog is part of our  Rails 6 series.

Rails 6 adds ActiveStorage::Blob#open which downloads a blob to a tempfile on disk and yields the tempfile.

1>> blob = ActiveStorage::Blob.first
2=> <ActiveStorage::Blob id: 1, key: "6qXeoibkvohP4VJiU4ytaEkH", filename: "Screenshot 2019-08-26 at 10.24.40 AM.png", ..., created_at: "2019-08-26 09:57:30">
3
4>> blob.open do |tempfile|
5>>   puts tempfile.path  #do some processing
6>> end
7# Output: /var/folders/67/3n96myxs1rn5q_c47z7dthj80000gn/T/ActiveStorage-1-20190826-73742-mve41j.png

Processing a blob

Let's take an example of a face detection application where the user images are uploaded. Let's assume that the images are uploaded on S3.

Before Rails 6, we will have to download the image in system's memory, process it with an image processing program and then send the processed image back to the S3 bucket.

The overhead

If the processing operation is successful, the original file can be deleted from the system. We need to take care of a lot of uncertain events from the download phase till the phase when the processed image is created.

ActiveStorage::Blob#open to the rescue

ActiveStorage::Blob#open, abstracts away all this complications and gives us a tempfile which is closed and unlinked once the block is executed.

 1. open takes care of handling all the fanfare of getting a blob object to a tempfile.  2. open takes care of the tempfile cleanup after the block.

1
2> > blob = ActiveStorage::Blob.first
3> > blob.open do |tempfile|
4> > tempfile #do some processing
5> > end
6
7# once the given block is executed
8
9# the tempfile is closed and unlinked
10
11=> #<Tempfile: (closed)>

By default, tempfiles are created in Dir.tmpdir directory, but ActiveStorage::Blob#open also takes an optional argument tmpdir to set a custom directory for storing the tempfiles.

1
2> > Dir.tmpdir
3> > => "/var/folders/67/3n96myxs1rn5q_c47z7dthj80000gn/T"
4
5> > blob = ActiveStorage::Blob.first
6> > blob.open(tmpdir: "/desired/path/to/save") do |tempfile|
7> > puts tempfile.path #do some processing
8> > end
9> >

Here is the relevant commit.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.