module Rooibos
The Elm Architecture for Ruby.
Building TUI applications means managing state, events, and rendering. Mixing them leads to spaghetti code. Bugs hide in the tangles.
This module implements The Elm Architecture (TEA). It separates your application into three pure functions: model, view, and update. The runtime handles the rest.
Use it to build applications with predictable, testable state management.
SPDX-License-Identifier: LGPL-3.0-or-later
++
Constants
- VERSION
-
The version of this gem. See semver.org/spec/v2.0.0.html
Public Class Methods
Source
# File lib/rooibos.rb, line 114 def self.delegate(message, prefix, child_update, child_model) return nil unless message.is_a?(Array) && message.first == prefix rest = message[1] new_child, command = child_update.call(rest, child_model) wrapped = command ? route(command, prefix) : nil [new_child, wrapped] end
Delegates a prefixed message to a child fragment’s UPDATE.
Parent fragment UPDATE functions route messages to child fragments. Each route requires pattern matching, calling the child, and rewrapping any returned command. The boilerplate adds up fast.
This method handles the dispatch. It checks the prefix, calls the child, and wraps any command. Returns nil if the prefix does not match.
- message
-
Incoming message (e.g.,
[:stats, :system_info, {...}]). - prefix
-
Expected prefix symbol (e.g.,
:stats). - child_update
-
The child’s UPDATE callable.
- child_model
-
The child’s current model.
Example
# Verbose: case message in [:stats, *rest] new_child, cmd = StatsPanel::Update.call(rest, model.stats) mapped = cmd ? Command.map(cmd) { |r| [:stats, *r] } : nil [new_child, mapped] end # Concise: Rooibos.delegate(message, :stats, StatsPanel::Update, model.stats)
Source
# File lib/rooibos.rb, line 62 def self.normalize_init(result) Runtime.normalize_init(result) end
Normalizes Init callable return value to [model, command] tuple.
Init callables use DWIM syntax. They can return just a model, just a command, or a full [model, command] tuple.
This method handles all formats. Use it when composing child fragment Inits in fractal architecture.
- result
-
The Init return value.
Examples
# Parent fragment composes children Init = ->(theme:) do stats_model, stats_cmd = Rooibos.normalize_init(StatsPanel::Init.(theme: theme)) network_model, network_cmd = Rooibos.normalize_init(NetworkPanel::Init.(theme: theme)) model = Model.new(stats: stats_model, network: network_model) command = Command.batch(stats_cmd, network_cmd) [model, command] end
Source
# File lib/rooibos.rb, line 84 def self.route(command, prefix) Command.map(command) { |result| [prefix, *result] } end
Wraps a command with a routing prefix.
Parent fragments trigger child fragment commands. The results need routing back to the correct child fragment. Manually wrapping every command is tedious.
This method prefixes command results automatically. Use it to route child fragment command results in Fractal Architecture.
- command
-
The child fragment command to wrap.
- prefix
-
Symbol prepended to results (e.g.,
:stats).
Example
# Verbose: Command.map(child_fragment.fetch_command) { |r| [:stats, *r] } # Concise: Rooibos.route(child_fragment.fetch_command, :stats)
Source
# File lib/rooibos.rb, line 29 def self.run(root_fragment = nil, **) Runtime.run(root_fragment, **) end
Starts the MVU event loop.
Convenience delegator to Runtime.run. See Runtime for full documentation.