Class: AtlasRb::Blob

Inherits:
Resource show all
Defined in:
lib/atlas_rb/blob.rb

Overview

The binary content backing a FileSet (or attached directly to a Work).

Blobs are the bytes-on-disk layer of the hierarchy. Operations on this class deal with raw octet streams: uploading new content, replacing content on an existing Blob, and streaming downloads via a chunk handler so very large files don't have to be buffered in memory.

See also: Work, FileSet.

Constant Summary collapse

ROUTE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Atlas REST endpoint prefix for this resource.

"/files/"

Class Method Summary collapse

Methods inherited from Resource

permissions, preview

Methods included from FaradayHelper

#connection, #multipart

Class Method Details

.content(id) {|chunk| ... } ⇒ Hash

Stream the Blob's binary content through a caller-supplied block.

The body is not buffered — each chunk Faraday receives is yielded to chunk_handler immediately, making this safe for files larger than available memory. The first chunk's response headers are captured and returned so callers can inspect Content-Type, Content-Length, etc.

Examples:

Stream to disk

File.open("/tmp/out.pdf", "wb") do |f|
  headers = AtlasRb::Blob.content("b-321") { |chunk| f.write(chunk) }
  puts headers["content-type"]
end

Parameters:

  • id (String)

    the Blob ID.

Yield Parameters:

  • chunk (String)

    the next chunk of binary data.

Returns:

  • (Hash)

    the response headers from GET /files/<id>/content.



46
47
48
49
50
51
52
53
54
55
# File 'lib/atlas_rb/blob.rb', line 46

def self.content(id, &chunk_handler)
  headers = {}
  connection({}).get("#{ROUTE}#{id}/content") do |req|
    req.options.on_data = proc do |chunk, _bytes_received, env|
      headers = env.response_headers if headers.empty? && env
      chunk_handler.call(chunk)
    end
  end
  headers
end

.create(id, blob_path, original_filename) ⇒ Hash

Upload a new Blob attached to a Work.

original_filename is preserved separately from the upload's File.basename(blob_path) because the on-disk path is often a temp file name (RackMultipart...tmp) — Atlas needs the user-facing name for download UX.

Examples:

AtlasRb::Blob.create("w-789", "/tmp/upload.tmp", "final_thesis.pdf")
# => { "id" => "b-321", "original_filename" => "final_thesis.pdf", ... }

Parameters:

  • id (String)

    the parent Work ID.

  • blob_path (String)

    path to the binary file on disk to upload.

  • original_filename (String)

    the user-facing filename Atlas should record (e.g. "final_thesis.pdf").

Returns:

  • (Hash)

    the created "blob" payload, including its "id".



73
74
75
76
77
78
79
80
81
# File 'lib/atlas_rb/blob.rb', line 73

def self.create(id, blob_path, original_filename)
  payload = { work_id: id,
              original_filename: original_filename,
              binary: Faraday::Multipart::FilePart.new(File.open(blob_path),
                                                      "application/octet-stream",
                                                      File.basename(blob_path)) }

  JSON.parse(multipart({}).post(ROUTE, payload)&.body)['blob']
end

.destroy(id) ⇒ Faraday::Response

Delete a Blob (the bytes and the metadata record).

Examples:

AtlasRb::Blob.destroy("b-321")

Parameters:

  • id (String)

    the Blob ID.

Returns:

  • (Faraday::Response)

    the raw delete response.



90
91
92
# File 'lib/atlas_rb/blob.rb', line 90

def self.destroy(id)
  connection({}).delete(ROUTE + id)
end

.find(id) ⇒ Hash

Fetch a single Blob's metadata record (not its bytes — see content).

Examples:

AtlasRb::Blob.find("b-321")
# => { "id" => "b-321", "original_filename" => "scan.pdf", ... }

Parameters:

  • id (String)

    the Blob ID.

Returns:

  • (Hash)

    the "blob" object, already unwrapped — typically includes "id", "original_filename", "size", and a download URL.



26
27
28
# File 'lib/atlas_rb/blob.rb', line 26

def self.find(id)
  JSON.parse(connection({}).get(ROUTE + id)&.body)['blob']
end

.update(id, blob_path) ⇒ Hash

Replace the bytes of an existing Blob in-place.

The Blob ID is preserved; only the underlying content changes. The original filename is not updated by this call — use a new create if you need a different original_filename.

Examples:

AtlasRb::Blob.update("b-321", "/tmp/revised.pdf")

Parameters:

  • id (String)

    the Blob ID.

  • blob_path (String)

    path to the replacement binary on disk.

Returns:

  • (Hash)

    the parsed JSON response from the patch.



106
107
108
109
110
111
# File 'lib/atlas_rb/blob.rb', line 106

def self.update(id, blob_path)
  payload = { binary: Faraday::Multipart::FilePart.new(File.open(blob_path),
                                                      "application/octet-stream",
                                                      File.basename(blob_path)) }
  JSON.parse(multipart({}).patch(ROUTE + id, payload)&.body)
end