Class: Coradoc::Mirror::HandlerRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/coradoc/mirror/handler_registry.rb

Overview

Open registry mapping CoreModel classes to handler modules.

Replaces closed case/when dispatch with an extensible registry. Third-party gems can register additional handlers without modifying core classes (OCP).

Lookup (including ancestor walking) is delegated to ‘Coradoc::Dispatch.hierarchical`. This class keeps the Entry shape and the handler-invocation semantics — those are mirror-specific.

Examples:

Registering a handler

registry = Coradoc::Mirror.default_registry
registry.register(MyCustomBlock, MyHandler)

Creating a custom registry

registry = Coradoc::Mirror::HandlerRegistry.new
registry.register(Coradoc::CoreModel::ParagraphBlock, MyParagraphHandler)

Defined Under Namespace

Classes: Entry

Instance Method Summary collapse

Constructor Details

#initializeHandlerRegistry

Returns a new instance of HandlerRegistry.



27
28
29
# File 'lib/coradoc/mirror/handler_registry.rb', line 27

def initialize
  @dispatch = Coradoc::Dispatch.hierarchical
end

Instance Method Details

#entry_for(element) ⇒ Entry?

Find the handler entry for a given CoreModel element.

Walks the element’s class ancestors (via Dispatch.hierarchical) to find the most specific registered handler. This allows registering a handler for a base class (e.g., Block) that applies to all subclasses, while also registering specific handlers for subclasses.

Parameters:

  • element (CoreModel::Base)

    element to find handler for

Returns:



64
65
66
# File 'lib/coradoc/mirror/handler_registry.rb', line 64

def entry_for(element)
  @dispatch.lookup(element.class)
end

#handle(element, context:) ⇒ Array(result, concat_flag)?

Invoke the handler for a given element.

Parameters:

  • element (CoreModel::Base)

    element to handle

  • context (CoreModelToMirror)

    transformer context

Returns:

  • (Array(result, concat_flag), nil)

    handler result or nil



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/coradoc/mirror/handler_registry.rb', line 77

def handle(element, context:)
  entry = entry_for(element)
  return nil unless entry

  kwargs = { context: context }.merge(entry.extra_kwargs || {})

  result = case entry.handler
           when Proc
             entry.handler.call(element, context)
           else
             entry.handler.public_send(entry.method_name, element, **kwargs)
           end

  [result, entry.concat]
end

#register(model_class, handler, method_name: :call, concat: false, extra_kwargs: {}) ⇒ Object

Register a handler for a CoreModel class.

Parameters:

  • model_class (Class)

    CoreModel class to handle

  • handler (Module, Class, Proc)

    handler implementation. If a Module/Class, method_name is called on it. If a Proc, called directly with (element, context:).

  • method_name (Symbol) (defaults to: :call)

    method to call on handler (default: :call)

  • concat (Boolean) (defaults to: false)

    if true, handler result is an array to concat into content rather than a single item to append

  • extra_kwargs (Hash) (defaults to: {})

    additional keyword arguments passed to the handler



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/coradoc/mirror/handler_registry.rb', line 42

def register(model_class, handler, method_name: :call, concat: false,
             extra_kwargs: {})
  @dispatch.register(
    model_class,
    Entry.new(
      handler: handler,
      method_name: method_name,
      concat: concat,
      extra_kwargs: extra_kwargs
    )
  )
end

#registered?(model_class) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/coradoc/mirror/handler_registry.rb', line 68

def registered?(model_class)
  @dispatch.registered?(model_class)
end