Class: CurrentScope::GatingReflection

Inherits:
Object
  • Object
show all
Defined in:
lib/current_scope/gating_reflection.rb

Overview

Answers one question about a controller path: is it PROVEN that current_scope_check! never runs there? True only when the callback is ABSENT from the class's callback chain — the one thing the chain states unconditionally. Everything else is false:

- callback present and unconditional → gated → false
- callback present wearing a condition (skip_before_action only:) →
UNPROVABLE without evaluating ActionFilter internals, which this class
must never do (KTD-3) → false. The naive any?/none? presence check
inverts exactly here — see the ProblemFrame characterization in
test/gating_reflection_test.rb — and per-action guessing is how a
fail-open gets reported as gated.
- no controller class routed at that path → nothing to prove → false

Absence is an EFFECT, not a cause: a bare skip_before_action, an inherited bare skip (#62), and never including Guard at all are the same verdict, because the chain looks the same. That is deliberate — the question is "does the gate run?", not "why not?".

Named beside GatingTripwire: both interrogate the same subject (is this action gated?), the tripwire at request time, this one by reflection.

Instance Method Summary collapse

Instance Method Details

#ungated?(controller_path) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/current_scope/gating_reflection.rb', line 24

def ungated?(controller_path)
  klass = controller_class_for(controller_path)
  # A controller without the callbacks API at all (a bare ActionController::
  # Metal without AbstractController::Callbacks) cannot run a before_action
  # — the gate PROVABLY never runs there. Without this check the reflection
  # would raise NoMethodError instead of answering. (#79 review)
  return true unless klass.respond_to?(:_process_action_callbacks)

  klass
    ._process_action_callbacks
    .none? { |callback| callback.kind == :before && callback.filter == :current_scope_check! }
rescue ActionDispatch::MissingController
  # A routed path with no controller class (a scaffolding leftover, a
  # not-yet-written controller) proves nothing about gating. Silent false,
  # matching the prove-or-stay-silent discipline of
  # warn_on_cross_controller_derivation.
  false
end