Class: Weft::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/weft/registry.rb,
lib/weft/registry/eligibility.rb

Overview

Stores registered Weft::Component and Weft::Page classes for the Router to consume at request time.

Components and Pages are stored separately because their lookup costs differ:

  • Components route at static paths (derived from the class name). Stored in @components; looked up via @path_index, a lazily-built hash keyed on the resolved path. O(1) lookup, invalidated when new components register.

  • Pages route at user-declared patterns that may include :param segments (e.g. /orders/:order_id). Stored in @pages; matched by walking the set and pattern-matching each page_path against the request path. O(n) match, but n is typically small (one entry per user-declared Page).

Because pages aren't in @path_index, register_page does not invalidate it. Unifying the two storage shapes would force pages-without- params into the linear walk OR invent two parallel code paths; keeping them separate is the simplest honest answer.

Defined Under Namespace

Modules: Eligibility

Instance Method Summary collapse

Constructor Details

#initializeRegistry

Returns a new instance of Registry.



36
37
38
39
40
41
42
# File 'lib/weft/registry.rb', line 36

def initialize
  @components = Set.new
  @pages = Set.new
  @path_index = nil
  @sse_present = nil
  @routes_validated = false
end

Instance Method Details

#any_sse_components?Boolean

True if any registered component declares pushes (i.e. participates in SSE streaming). Used by Weft::Page to decide whether to emit the htmx-ext-sse script tag automatically. One-way memoized: recomputed while still false, so components registered after an earlier render are picked up; once true it sticks, so the typical load-everything-then-serve pattern pays no steady-state recompute cost.

Returns:

  • (Boolean)


116
117
118
119
120
# File 'lib/weft/registry.rb', line 116

def any_sse_components?
  return true if @sse_present

  @sse_present = @components.any?(&:push_config)
end

#clearObject

Empty the registry. The evict-everything reset for hand-rolled reload integrations and for tests; per-class eviction is #evict.



60
61
62
63
64
65
66
# File 'lib/weft/registry.rb', line 60

def clear
  @components.clear
  @pages.clear
  @path_index = nil
  @sse_present = nil
  @routes_validated = false
end

#componentsObject



106
107
108
# File 'lib/weft/registry.rb', line 106

def components
  @components.to_a
end

#evict(klass) ⇒ Object

Remove one class from the registry, invalidating route lookup so a fresh same-path registration serves cleanly. This is the reload-eviction primitive: Weft.configure_autoloading wires it to Zeitwerk's on_unload callback, and hand-rolled reloaders should call it (or #clear) as classes unload. Safe to call with any object — non-registered classes (models, service objects) fall through untouched. Returns true if evicted.



74
75
76
77
78
79
80
81
# File 'lib/weft/registry.rb', line 74

def evict(klass) # rubocop:disable Naming/PredicateMethod -- a command with a did-evict status return
  return false unless @components.delete?(klass) || @pages.delete?(klass)

  @path_index = nil
  @sse_present = nil
  @routes_validated = false
  true
end

#lookup(path) ⇒ Object



101
102
103
104
# File 'lib/weft/registry.rb', line 101

def lookup(path)
  validate_routes!
  path_index[path]
end

#match_page(path) ⇒ Object

Match a request path against registered page patterns. Non-routable pages (abstract bases, classes without a resolvable path) are skipped. Returns [page_class, extracted_params] or nil.



90
91
92
93
94
95
96
97
98
99
# File 'lib/weft/registry.rb', line 90

def match_page(path)
  validate_routes!
  @pages.each do |page_class|
    next unless page_class.routable?

    params = match_pattern(resolved_page_pattern(page_class), path)
    return [page_class, params] if params
  end
  nil
end

#pagesObject



83
84
85
# File 'lib/weft/registry.rb', line 83

def pages
  @pages.to_a
end

#register(component_class) ⇒ Object



44
45
46
47
48
# File 'lib/weft/registry.rb', line 44

def register(component_class)
  @components.add(component_class)
  @path_index = nil
  @routes_validated = false
end

#register_page(page_class) ⇒ Object

No @path_index invalidation: pages aren't indexed there (see the class comment above). Pages do participate in collision detection, so the route-validation memo is cleared.



53
54
55
56
# File 'lib/weft/registry.rb', line 53

def register_page(page_class)
  @pages.add(page_class)
  @routes_validated = false
end