Class: ActiveStorage::Ocr::Binary

Inherits:
Object
  • Object
show all
Defined in:
lib/activestorage/ocr/binary.rb

Overview

Manages the OCR server binary.

Handles downloading pre-built binaries from GitHub releases and detecting the appropriate platform.

Supported Platforms

  • darwin-x86_64 (macOS Intel)
  • darwin-aarch64 (macOS Apple Silicon)
  • linux-x86_64 (Linux x86_64)
  • linux-aarch64 (Linux ARM64)

Binary Variants

  • :ocrs - Pure Rust OCR engine only (~15MB, no system dependencies)
  • :leptess - Tesseract OCR engine only (~50-80MB, no system dependencies)
  • :all - Both engines included (~80-100MB)

Usage

# Install the default (ocrs) binary for the current platform
ActiveStorage::Ocr::Binary.install!

# Install the leptess variant
ActiveStorage::Ocr::Binary.install!(variant: :leptess)

# Install all-engines variant
ActiveStorage::Ocr::Binary.install!(variant: :all)

# Check if binary is installed
ActiveStorage::Ocr::Binary.installed?  # => true

# Get the path to the binary
ActiveStorage::Ocr::Binary.binary_path

Constant Summary collapse

GITHUB_REPO =

GitHub repository for downloading releases.

"Cause-of-a-Kind/activestorage-ocr"
BINARY_NAME =

Name of the server binary.

"activestorage-ocr-server"
VARIANTS =

Available binary variants with their download suffix and descriptions.

{
  ocrs: {
    suffix: "",
    description: "Pure Rust OCR engine (fast, no system dependencies)"
  },
  leptess: {
    suffix: "-leptess",
    description: "Tesseract OCR engine (better for messy images)"
  },
  all: {
    suffix: "-all",
    description: "All OCR engines included"
  }
}.freeze

Class Method Summary collapse

Class Method Details

.available_variants ⇒ Object

Lists available binary variants.

Returns

Array of variant names.



161
162
163
# File 'lib/activestorage/ocr/binary.rb', line 161

def available_variants
  VARIANTS.keys
end

.binary_path ⇒ Object

Returns the path where the binary is installed.

Returns

Absolute path to the binary.



102
103
104
# File 'lib/activestorage/ocr/binary.rb', line 102

def binary_path
  @binary_path ||= File.join(install_dir, BINARY_NAME)
end

.download_url(variant: :ocrs) ⇒ Object

Returns the download URL for the current platform and variant.

Parameters

  • variant - The binary variant (:ocrs, :leptess, or :all)

Returns

GitHub releases URL for the platform-specific tarball.



147
148
149
150
151
152
153
154
# File 'lib/activestorage/ocr/binary.rb', line 147

def download_url(variant: :ocrs)
  variant = variant.to_sym
  validate_variant!(variant)
  tag = "v#{version}"
  suffix = VARIANTS[variant][:suffix]
  filename = "activestorage-ocr-server#{suffix}-#{platform}.tar.gz"
  "https://github.com/#{GITHUB_REPO}/releases/download/#{tag}/#{filename}"
end

.gem_root ⇒ Object

Returns the gem's root directory.



118
119
120
# File 'lib/activestorage/ocr/binary.rb', line 118

def gem_root
  @gem_root ||= File.expand_path("../../../..", __FILE__)
end

.install!(force: false, path: nil, variant: :ocrs) ⇒ Object

Downloads and installs the binary.

Downloads from GitHub releases and extracts to the specified directory.

Parameters

  • force - If true, reinstalls even if already installed
  • path - Custom installation directory (defaults to gem's bin directory)
  • variant - The binary variant to install (:ocrs, :leptess, or :all)

Returns

Path to the installed binary.

Raises

RuntimeError if the download fails. ArgumentError if an invalid variant is specified.



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/activestorage/ocr/binary.rb', line 197

def install!(force: false, path: nil, variant: :ocrs)
  validate_variant!(variant)
  target_dir = path || install_dir
  target_path = File.join(target_dir, BINARY_NAME)

  if !force && File.executable?(target_path)
    puts "Binary already installed at #{target_path}"
    return target_path
  end

  FileUtils.mkdir_p(target_dir)

  variant_desc = VARIANTS[variant][:description]
  puts "Downloading activestorage-ocr-server (#{variant_desc}) for #{platform}..."

  url = download_url(variant: variant)
  uri = URI(url)
  response = fetch_with_redirects(uri)

  unless response.is_a?(Net::HTTPSuccess)
    feature_flag = variant == :ocrs ? "engine-ocrs" : (variant == :leptess ? "engine-leptess" : "all-engines")
    raise "Failed to download binary: #{response.code} #{response.message}\n" \
          "URL: #{url}\n" \
          "You may need to build from source: cd rust && cargo build --release --features #{feature_flag}"
  end

  extract_binary(response.body, target_path)
  puts "Installed to #{target_path}"
  target_path
end

.install_dir ⇒ Object

Returns the installation directory.

Creates the directory if it doesn't exist.



109
110
111
112
113
114
115
# File 'lib/activestorage/ocr/binary.rb', line 109

def install_dir
  @install_dir ||= begin
    dir = File.join(gem_root, "bin")
    FileUtils.mkdir_p(dir)
    dir
  end
end

.installed? ⇒ Boolean

Checks if the binary is installed and executable.

Returns

true if the binary exists and is executable.

Returns:

  • (Boolean)


127
128
129
# File 'lib/activestorage/ocr/binary.rb', line 127

def installed?
  File.executable?(binary_path)
end

.platform ⇒ Object

Detects the current platform.

Returns

A String like "darwin-x86_64" or "linux-aarch64".

Raises

RuntimeError if the OS or architecture is unsupported.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/activestorage/ocr/binary.rb', line 79

def platform
  os = case RbConfig::CONFIG["host_os"]
       when /darwin/i then "darwin"
       when /linux/i then "linux"
       else
         raise "Unsupported OS: #{RbConfig::CONFIG['host_os']}"
       end

  arch = case RbConfig::CONFIG["host_cpu"]
         when /x86_64|amd64/i then "x86_64"
         when /arm64|aarch64/i then "aarch64"
         else
           raise "Unsupported architecture: #{RbConfig::CONFIG['host_cpu']}"
         end

  "#{os}-#{arch}"
end

.variant_info(variant) ⇒ Object

Returns info about a specific variant.

Parameters

  • variant - The variant name (:ocrs, :leptess, or :all)

Returns

Hash with :suffix and :description keys.



174
175
176
177
# File 'lib/activestorage/ocr/binary.rb', line 174

def variant_info(variant)
  validate_variant!(variant)
  VARIANTS[variant]
end

.version ⇒ Object

Returns the gem version.

Used to determine which release to download.



134
135
136
# File 'lib/activestorage/ocr/binary.rb', line 134

def version
  ActiveStorage::Ocr::VERSION
end