Skip to content

Exports

An import returns exactly the Entrypoint’s Export. Minimal exports a module; this example covers a Hash, a callable, and a distinct adapter Entrypoint for an existing file with no export. It needs no gems or Bundler. Source on GitHub.

File Import returns How the app uses it
settings.rb A plain Hash from export currency: 'USD' Pattern matching extracts currency
formatter.rb A Proc money.call(4_200) formats cents
legacy_adapter.rb A plain Hash containing prefix and a captured label method Pattern matching extracts values; label.call(42) calls the method
settings.rb
# Export: keywords are one Hash, returned directly to the Importer.
export currency: 'USD'
formatter.rb
# Export: a callable, returned as is; no wrapper or namespace is added.
export ->(cents) { format('%.2f', cents / 100.0) }

legacy.rb is ordinary Ruby with a constant and a top-level method. The adapter requires it inside its Carton Box, so PREFIX does not become a constant in Main:

legacy.rb
# Ordinary Ruby with no Carton calls. The adapter requires this in its own Box.
PREFIX = 'INV'
def label(number) = "#{PREFIX}-#{number.to_s.rjust(4, '0')}"

legacy_adapter.rb is the imported Entrypoint. It explicitly exports the chosen constant value and captured method:

legacy_adapter.rb
# Load existing code inside this Carton and explicitly choose its Export.
require_relative 'legacy'
# Export: a Hash of the values Importers need, not the legacy constants.
export prefix: PREFIX, label: method(:label)
main.rb
require 'carton'
# Carton boundary: each Entrypoint runs in its own Carton Box and explicitly
# exports a value.
settings = import_relative 'settings'
money = import_relative 'formatter'
legacy = import_relative 'legacy_adapter'
# Hash Exports use Ruby's own pattern matching, including Method values.
settings => { currency: }
legacy => { label:, prefix: }
puts "#{label.call(42)}: #{currency} #{money.call(4_200)}"
puts "Captured method: #{label.call(7)}"
puts "Legacy prefix: #{prefix}"
puts "PREFIX defined in Main: #{!defined?(PREFIX).nil?}"

The app binds the adapter’s Hash to legacy, then extracts label and prefix through pattern matching. label is a Method, which the app calls with .call. The original file stays unchanged, and the adapter chooses what crosses the Carton boundary.

Every Shared Import returns the same Export. If you export a mutable Hash, every Importer gets that same Hash, so freeze it if it is meant to be read-only.

RUBY_BOX=1 ruby examples/exports/main.rb
INV-0042: USD 42.00
Captured method: INV-0007
Legacy prefix: INV
PREFIX defined in Main: false

See Exporting for the rules.