Module: Rhino::Routing::RouteGroupValidator

Defined in:
lib/rhino/routing/route_group_validator.rb

Overview

Validates the configured route groups before any routes are drawn and raises Rhino::RouteGroupConflictError when two groups would silently shadow each other.

A route group’s routing identity is the pair (host-set, prefix), per model. Two groups conflict when ALL of the following hold:

1. Their host-sets intersect. A group with no `domain:` (nil/blank)
   matches EVERY host (a wildcard), so it intersects with anything. Two
   groups with an identical, non-empty domain pattern also intersect.
   Two groups with different non-empty domain patterns are disjoint.
2. They share the same effective prefix (nil and "" are the same root).
3. Their model sets overlap (`:all`/`"*"` expands to every registered
   model; explicit slug lists overlap on intersection).

This encodes the rule: with a distinguishing domain, the prefix is optional (root is fine — the host disambiguates); without a domain, the prefix is the only disambiguator, so two or more overlapping groups must use distinct prefixes.

Note: this is a conservative, static check. Exotic cross-pattern overlaps (e.g. a literal host that also satisfies another group’s “param.example.com”) are not statically detected.

Class Method Summary collapse

Class Method Details

.validate(config) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rhino/routing/route_group_validator.rb', line 34

def validate(config)
  groups = config.route_groups
  names = groups.keys

  validate_legacy_auth_collision!(config)

  names.combination(2).each do |a_name, b_name|
    a = groups[a_name]
    b = groups[b_name]

    next unless host_sets_intersect?(a, b)
    next unless normalize_prefix(a) == normalize_prefix(b)

    shared = config.models_for_group(a_name) & config.models_for_group(b_name)
    next if shared.empty?

    raise RouteGroupConflictError, message(a_name, b_name, a, b, shared)
  end
end