Class: PatternRuby::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/pattern_ruby/router.rb

Constant Summary collapse

MAX_INPUT_LENGTH =

Maximum input length for matching (100 KB). Inputs beyond this are truncated.

100_000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Router

Returns a new instance of Router.



8
9
10
11
12
13
14
15
16
# File 'lib/pattern_ruby/router.rb', line 8

def initialize(&block)
  @intents = []
  @intent_names = {}
  @fallback_handler = nil
  @entity_registry = EntityTypes::Registry.new
  @compiler = PatternCompiler.new(entity_registry: @entity_registry)
  @mutex = Mutex.new
  instance_eval(&block) if block
end

Instance Attribute Details

#intentsObject (readonly)

Returns the value of attribute intents.



3
4
5
# File 'lib/pattern_ruby/router.rb', line 3

def intents
  @intents
end

Instance Method Details

#entity_type(name, **options) ⇒ Object



38
39
40
# File 'lib/pattern_ruby/router.rb', line 38

def entity_type(name, **options)
  @entity_registry.register(name, **options)
end

#fallback(&block) ⇒ Object



34
35
36
# File 'lib/pattern_ruby/router.rb', line 34

def fallback(&block)
  @fallback_handler = block
end

#intent(name, &block) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/pattern_ruby/router.rb', line 18

def intent(name, &block)
  name_sym = name.to_sym
  if @intent_names.key?(name_sym)
    # Duplicate registration: return existing intent (idempotent)
    return @intent_names[name_sym]
  end

  i = Intent.new(name, compiler: @compiler)
  i.instance_eval(&block) if block
  @mutex.synchronize do
    @intents << i
    @intent_names[name_sym] = i
  end
  i
end

#match(input, context: nil) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/pattern_ruby/router.rb', line 42

def match(input, context: nil)
  input = sanitize_input(input)
  return fallback_result(input) if input.empty?

  candidates = []

  @mutex.synchronize { @intents.dup }.each do |i|
    # Skip intents that require a specific context
    if i.context_requirement
      next unless context == i.context_requirement
    end

    result = i.match(input, entity_registry: @entity_registry)
    candidates << result if result
  end

  return candidates.max_by(&:score) unless candidates.empty?

  fallback_result(input)
end

#match_all(input, context: nil) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/pattern_ruby/router.rb', line 63

def match_all(input, context: nil)
  input = sanitize_input(input)
  return [] if input.empty?

  candidates = []

  @mutex.synchronize { @intents.dup }.each do |i|
    if i.context_requirement
      next unless context == i.context_requirement
    end

    result = i.match(input, entity_registry: @entity_registry)
    candidates << result if result
  end

  candidates.sort_by { |r| -r.score }
end