July 30, 2018·4 min read·engineeringrubyrailsstorage

Rails 5.2.1 RC1 fixes the empty direct-upload path

Rails 5.2.1 RC1 corrects Active Storage uploads for zero-byte files and fixes the metadata response shape. The empty-file case exposes a missing transition in chunked checksum calculation.

A zero-byte file has content of length zero and still needs to complete an upload workflow. Active Storage's browser checksum implementation divided files into chunks, but an empty file has no ordinary chunk to start that process. Rails 5.2.1 RC1 includes a correction that gives the empty case an explicit first read.

The July 30 release-candidate announcement asks applications to look for regressions before the planned final release. Its Active Storage changelog names two corrections since 5.2.0, zero-byte direct uploads and removal of a JSON root from the direct-upload creation response.

These are small maintenance items with specific consequences for the new attachment workflow. One determines whether the browser reaches checksum completion. The other determines whether the server returns the object shape the client expects. Neither requires a new application-level attachment abstraction.

I appreciate Ruby APIs that keep common operations readable. The browser portion of an attachment workflow still needs explicit state transitions underneath that API. This candidate's empty-file fix is a useful example because it concerns a valid input that has no ordinary iteration step.

Zero chunks still require completion

The candidate's FileChecksum implementation divides the file size by a fixed chunk size and rounds up to determine the chunk count. It initializes the chunk index to zero. Creation installs FileReader callbacks and asks to read the next chunk.

For a nonempty file, the next-chunk condition succeeds while the index is smaller than the count. Reading triggers a load event, which appends data to the checksum state. The handler then either schedules another read or finalizes the digest and calls the completion callback.

An empty file has both index and count equal to zero at the start. A condition requiring only index less than count would never schedule the initial read. The load handler that normally finalizes the checksum would consequently have no read event to process.

The corrected condition permits a read when both values are zero. The requested slice starts and ends at zero, representing the empty contents. After scheduling that read, the implementation increments the index, so the special case applies only once.

On the resulting load event, another next-chunk request returns false. The handler can finalize the checksum and report it through the normal callback. This preserves the existing completion path while providing the event needed to enter it.

The useful distinction is between having no bytes and having no operation to complete. A checksum over empty content still has a result. The asynchronous implementation needs a route to deliver that result even when the ordinary chunk loop has no iterations.

Direct upload has a metadata response

The direct-uploads controller creates a blob before the browser sends the file to its storage service. Its comments describe submitting the signed blob identifier with the form after upload completes.

The controller accepts metadata including filename, byte size and checksum. It returns the blob representation with a signed identifier and a direct-upload object containing the service URL and required headers. This is the application-side preparation for a subsequent storage request.

The candidate explicitly calls the blob's JSON conversion with root: false. That keeps the blob fields at the expected level in the response, alongside the direct-upload information. A root wrapper would change that structure.

This is a protocol detail between the browser library and Rails. Returning valid JSON is insufficient if the fields occupy a different level than the client uses. The correction makes the endpoint's response structure explicit at the point of serialization.

A candidate collects evidence about the changed paths

Rafael França's announcement says the final release is expected on August 6 if no regressions are found. That remains a plan as of this candidate. The request for reports names the maintainer to mention when opening an issue.

The upload corrections suggest focused cases for examining this candidate. An empty file exercises the special initial read, while an ordinary file still exercises the chunk loop. The metadata endpoint's response can establish whether root configuration changes its object structure.

My preference is for that evidence to follow the mechanism that changed. A successful upload of one ordinary image would say little about the zero-chunk path. The candidate's source makes the missing case precise enough to examine without guessing which attachment behavior motivated the maintenance work.

The announcement also supplies SHA256 checksums for the component gems. Those identify the published candidate artifacts, while the tagged changelog identifies the fixes being qualified. For Active Storage, RC1's substantive changes ensure that empty content reaches checksum completion and that the pre-upload metadata response retains its intended shape.