Prohlížeč zdrojového kódu
docs/specs/examples-runner.md
Spec: Examples Runner
- Status: active
- Created: 2026-03-05
- Related code:
app/services/scenario_runner.rb,app/controllers/examples_controller.rb,app/views/examples/
Overview
Visitors can interactively run code examples from the detail page. Each example may define one or more scenarios, each with a set of dropdown inputs. The user selects parameter values and submits; the example code executes server-side and the result appears inline without a full page reload.
Behaviour
Scenarios and inputs
- An example may define zero or more named scenarios.
- Each scenario has a name, an optional description, and zero or more inputs.
- Each input has a label and a fixed list of allowed options; only dropdown selection is possible — no free-text entry. The input's variable name is shown alongside the label so visitors can see which local variable the selected value is bound to.
- Each scenario is displayed as a separate card on the example detail page, with its own form and result area.
Submitting a scenario
- The user selects a value for each input from the dropdown and clicks "Spustit".
- The form submits via Turbo Frame; only the result area for that scenario updates — the rest of the page is unchanged.
- The server validates that the selected value for each input is one of the allowed options. Any invalid or missing value results in a
422 Unprocessable Entityresponse.
Boilerplate code display
- Each scenario card shows its
boilerplate_filecontent as a syntax-highlighted, read-only code block above the input form.
Execution
- If the example has a
source_file, it is loaded into an anonymous module first; the scenario'sboilerplate_filesnippet is then evaluated inside the same module context. - If there is no
source_file, the boilerplate snippet is evaluated in a fresh anonymous module — it must be fully self-contained. - Input values are pre-bound as local variables matching each input's
namefield before the boilerplate snippet is evaluated. - Output is captured by overriding
putswithin the execution context; the snippet usesputslike ordinary Ruby. Captured output becomes the displayed result string. - Execution is capped at a 5-second timeout. If exceeded, a Czech error message is shown.
- Any Ruby exception during execution is caught; a Czech-language error string including the exception class and message is shown.
- On success, the captured output and execution duration (in seconds, 4 decimal places) are displayed.
Result display
- Success: output text in a styled box, followed by a completion time.
- Failure (timeout or exception): error message in a styled error box.
Implementation Notes
ScenarioRunnerloadssource_fileinto an anonymousModuleviamodule_eval, so example classes do not leak into the global namespace.- Input locals are prepended to the snippet as literal assignment statements (
name = "Alice"\n...) beforemodule_eval, keeping the snippet source readable without metaprogramming. $stdoutis replaced with aStringIOinstance during snippet evaluation and restored in anensureblock;putsin the snippet writes to the captured buffer naturally.- Execution uses
Timeout.timeout(5);Timeout::Errorand all other exceptions are rescued separately. ScenarioRunner.runtakessource_file:(may benil),boilerplate_file:, andinputs:— noentry_classorentry_method. Whensource_fileisnil, the module_eval of the source file is skipped.- The Turbo Frame tag for each scenario result is
scenario_result_<index>; the form targets the same frame so only that area re-renders. - Input validation in the controller checks both presence and membership in
input.optionsbefore callingScenarioRunner.
Tests
spec/services/scenario_runner_spec.rb— puts output capture, local variable binding, exception handling, timeout, module isolation
See Also
- Examples System — defines the example structure, metadata, and registry the runner operates on.
- Rich Example Content — scenario forms are embedded via placeholder tags in the example's Markdown content.
- Styling and CSS —
.result-boxstyles the execution output area;.code-blockstyles inline code display.
Change Log
- 2026-03-05: Initial retrospective spec.
- 2026-03-09: Prospective update — boilerplate snippet model; removed entry_class/entry_method; added boilerplate_file per scenario, local-variable input binding, puts-capture output.
- 2026-03-23: Prospective update —
source_fileis optional; runner skips source loading when nil.