feat: implement EventProjection base class with declarative mapping #316

Merged
freemo merged 2 commits from feature/m2-event-projection into master 2026-03-16 19:53:08 +00:00
Owner

Summary

Implements Issue #303: EventProjection base class with declarative domain-event-to-RenderOp mapping.

Changes

  • EventProjection (lib/aethyr/core/render/event_projection.rb): Base class providing on DSL for declaring event handlers that map domain events to RenderOps
  • ProjectionRegistry (lib/aethyr/core/render/projection_registry.rb): Singleton registry for managing projection classes with register, project, and lookup methods

Key Features

  • on class-level DSL for declaring event-to-RenderOp mappings
  • Handlers receive events and return one or more RenderOps
  • Multiple projections can handle the same event type (ops concatenated in registration order)
  • Unknown event types gracefully return empty arrays
  • Full YARD documentation

Testing

  • Unit tests: 26 scenarios, 94 steps - all passing
  • Integration tests: 8 scenarios, 33 steps - all passing
  • Rubocop: No offenses detected

Example Usage

class RoomProjection < EventProjection
  on :entity_entered_room do |event|
    RenderOp.text_append(
      window: :main,
      text: "#{event.entity.short_desc} arrives from the #{event.direction}."
    )
  end
end

ProjectionRegistry.register(RoomProjection)
ops = ProjectionRegistry.project(:entity_entered_room, event)
# => [RenderOp.text_append(...)]

Dependencies

This PR depends on #304 (RenderOp Model) which is included via the feature/m2-render-ops base branch.

Closes #303

## Summary Implements Issue #303: EventProjection base class with declarative domain-event-to-RenderOp mapping. ### Changes - **EventProjection** (`lib/aethyr/core/render/event_projection.rb`): Base class providing `on` DSL for declaring event handlers that map domain events to RenderOps - **ProjectionRegistry** (`lib/aethyr/core/render/projection_registry.rb`): Singleton registry for managing projection classes with `register`, `project`, and lookup methods ### Key Features - `on` class-level DSL for declaring event-to-RenderOp mappings - Handlers receive events and return one or more RenderOps - Multiple projections can handle the same event type (ops concatenated in registration order) - Unknown event types gracefully return empty arrays - Full YARD documentation ### Testing - **Unit tests**: 26 scenarios, 94 steps - all passing - **Integration tests**: 8 scenarios, 33 steps - all passing - **Rubocop**: No offenses detected ### Example Usage ```ruby class RoomProjection < EventProjection on :entity_entered_room do |event| RenderOp.text_append( window: :main, text: "#{event.entity.short_desc} arrives from the #{event.direction}." ) end end ProjectionRegistry.register(RoomProjection) ops = ProjectionRegistry.project(:entity_entered_room, event) # => [RenderOp.text_append(...)] ``` ### Dependencies This PR depends on #304 (RenderOp Model) which is included via the `feature/m2-render-ops` base branch. Closes #303
Implements the RenderOp value object class for the UI render pipeline as
specified in issue #304. RenderOps are immutable value objects that describe
rendering instructions without specifying how they should be rendered.

Key features:
- Immutable value objects (frozen after creation) with type, window, and data
- Seven core RenderOp types: text_append, map_refresh, bar_update,
  prompt_update, window_clear, overlay_show, overlay_hide
- Factory methods for convenient construction: RenderOp.text_append(),
  RenderOp.bar_update(), etc.
- Data validation per type (required fields are enforced)
- Equality comparison support (== and hash for use as hash keys)
- to_h serialization for logging and debugging
- Comprehensive YARD documentation

Testing:
- 36 Cucumber scenarios covering all factory methods, immutability,
  validation, equality, and type constants
- 3 integration scenarios for realistic usage patterns

ISSUES CLOSED: #304
freemo force-pushed feature/m2-event-projection from efdec87237 to 6d3f84da0f 2026-03-16 16:55:31 +00:00 Compare
freemo force-pushed feature/m2-event-projection from 6d3f84da0f to 07936e53fb 2026-03-16 17:30:38 +00:00 Compare
freemo force-pushed feature/m2-event-projection from 07936e53fb to 1f8f011d25 2026-03-16 19:52:58 +00:00 Compare
freemo merged commit 1f8f011d25 into master 2026-03-16 19:53:08 +00:00
freemo deleted branch feature/m2-event-projection 2026-03-16 19:53:09 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: aethyr/Aethyr#316
No description provided.