Skip to content
Pages

Adapters

An adapter is how Ezu boots your app and asks it questions, so the core never learns what Rails is. Each slot gets its own adapter instance, with its own working directory, port and clock.

After reading this page, you will know:

  • What every adapter answers.
  • What the Rails adapter does, and its options.
  • How to map an app that isn't Rails.

The interface

Method Answers
prepare Make a throwaway copy of the app, once per run.
prepare_from(prepared) Copy that for one slot.
routes Every GET route: {path, regexp, page_id}.
translations(locales) Every translation, as flat dotted keys per locale.
seed(script, slot) Run the seed for one slot and return its JSON.
start / stop / base_url The slot's server.
blocked / hidden URL globs to abort, and CSS selectors to hide, such as development tools.

Rails

adapter :rails,
  prepare: %w[db:schema:load tailwindcss:build],   # rails tasks run once, before the slots
  env: { "WARIWARI_RELEASE_ID" => "atlas" },        # extra environment for every process
  health_path: "/up"                                # answers 200 once the server is up

What it does:

  • Runs every process with RAILS_ENV=development and DATABASE_URL pointing at a SQLite file in tmp/ezu-work/, so the app's own databases are never touched. prepare loads the schema there, and each slot gets a copy.
  • Reads routes with bin/rails runner: GET routes for HTML, named controller#action.
  • Reads translations from I18n.
  • Runs ezu/seed.rb with bin/rails runner, with EZU_SEED_OUT, EZU_SLOTS, EZU_LOCALE and EZU_VIEWPORT set.
  • Starts bin/rails server on the slot's port.
  • Preloads repeatable.rb into every process through RUBYOPT: Time.now reads Ezu's clock file, and SecureRandom, rand, sample and shuffle draw from seeded sequences. See Repeatable runs.
  • Blocks the mini-profiler and Tensaku's event stream, and hides Tensaku's button, so development tools never land in a screenshot.

A docs site with no database, like this one, passes prepare: %w[tailwindcss:build] and health_path: "/".

Command

For any app started by a shell command:

adapter :command,
  start: "exec ruby server.rb",           # must listen on $PORT
  routes: "routes.json",                   # [{ "path": "/items/:id", "page_id": "items#show" }]
  translations: "translations.json",       # { "en": { "items.details": "Details" } }
  seed: "bin/seed",                        # writes JSON keyed by slot name to $EZU_SEED_OUT
  health_path: "/health",
  hidden: [ "dev-tool" ]

The app gets PORT, EZU_CLOCK_FILE and EZU_RANDOM_SEED, and is only repeatable if it honours them: read the time from the clock file, and seed its randomness. Ezu's own end-to-end test maps a tiny app this way, in test/fixtures/app/.