Module: Phlex::Reactive

Defined in:
lib/phlex/reactive.rb,
lib/phlex/reactive/engine.rb,
lib/phlex/reactive/version.rb,
lib/phlex/reactive/response.rb,
lib/phlex/reactive/component.rb,
lib/phlex/reactive/streamable.rb,
app/controllers/phlex/reactive/actions_controller.rb,
lib/generators/phlex/reactive/install/install_generator.rb,
lib/generators/phlex/reactive/component/component_generator.rb

Overview

phlex-reactive: reactive Phlex components for Rails.

Two cooperating mixins, one client runtime, one endpoint:

* Phlex::Reactive::Streamable — gives a component a stable `id` and class
  methods to render itself as a Turbo Stream (`.replace`, `.append`, ...)
  and to broadcast itself (`.broadcast_replace_to`, ...). The server->client
  half (controller responses + background broadcasts).

* Phlex::Reactive::Component — declares client-invokable `action`s and
  emits a signed identity token + the wiring the generic `reactive`
  Stimulus controller needs. The client->server half (clicks, form input).

Both halves converge on ONE re-render unit: the component, targeted by its ‘id`. See the README for the mental model and examples.

Defined Under Namespace

Modules: Component, Generators, Streamable Classes: ActionsController, Engine, Error, InvalidToken, Response

Constant Summary collapse

IDENTITY_PURPOSE =

Purpose string bound into every identity token’s signature so a token minted for phlex-reactive can’t be replayed against another verifier use.

"phlex-reactive/identity"
VERSION =
"0.2.6"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.action_pathObject



69
70
71
# File 'lib/phlex/reactive.rb', line 69

def action_path
  @action_path ||= "/reactive/actions"
end

.authorization_errorsObject

Exception classes the action endpoint renders as 403. Append your authorization library’s error (Pundit::NotAuthorizedError, ActionPolicy::Unauthorized, …).



61
62
63
# File 'lib/phlex/reactive.rb', line 61

def authorization_errors
  @authorization_errors
end

.base_controller_nameObject



101
102
103
# File 'lib/phlex/reactive.rb', line 101

def base_controller_name
  @base_controller_name ||= "ActionController::Base"
end

.flash_targetObject

DOM id of the host-app container a Response#flash appends into. Default “flash”; override to match your layout’s flash region.



83
84
85
# File 'lib/phlex/reactive.rb', line 83

def flash_target
  @flash_target ||= "flash"
end

.rendererObject



77
78
79
# File 'lib/phlex/reactive.rb', line 77

def renderer
  @renderer ||= defined?(::ActionController::Base) ? ::ActionController::Base : nil
end

.verifierObject



73
74
75
# File 'lib/phlex/reactive.rb', line 73

def verifier
  @verifier ||= default_verifier
end

Class Method Details

.base_controllerObject



105
106
107
# File 'lib/phlex/reactive.rb', line 105

def base_controller
  base_controller_name.constantize
end

.current_connection_idObject

The acting client’s SSE connection id during an action, or nil. Set by the ActionsController from the X-Pgbus-Connection header. A component action passes ‘exclude: Phlex::Reactive.current_connection_id` (or the `reactive_connection_id` helper) to suppress the actor’s own broadcast echo.



124
125
126
# File 'lib/phlex/reactive.rb', line 124

def current_connection_id
  Thread.current[:phlex_reactive_connection_id]
end

.flash_builderObject

A Turbo::Streams::TagBuilder bound to an off-request view context, used to build standalone streams (e.g. a Response flash append) not tied to a specific component’s id.



97
98
99
# File 'lib/phlex/reactive.rb', line 97

def flash_builder
  ::Turbo::Streams::TagBuilder.new(renderer.new.view_context)
end

.render(component) ⇒ Object

Render a Phlex component to HTML with a full (off-request) view context.



90
91
92
# File 'lib/phlex/reactive.rb', line 90

def render(component)
  renderer.render(component, layout: false)
end

.sign(payload) ⇒ Object

Signs a payload hash into an identity token.



115
116
117
# File 'lib/phlex/reactive.rb', line 115

def sign(payload)
  verifier.generate(payload, purpose: IDENTITY_PURPOSE)
end

.verify(token) ⇒ Object

Returns the verified payload hash, or nil if the token is invalid.



110
111
112
# File 'lib/phlex/reactive.rb', line 110

def verify(token)
  verifier.verified(token, purpose: IDENTITY_PURPOSE)
end

.with_connection_id(connection_id) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/phlex/reactive.rb', line 128

def with_connection_id(connection_id)
  previous = Thread.current[:phlex_reactive_connection_id]
  Thread.current[:phlex_reactive_connection_id] = connection_id.presence
  yield
ensure
  Thread.current[:phlex_reactive_connection_id] = previous
end