Module: Ruact::ServerFunctions::QueryDispatch

Defined in:
lib/ruact/server_functions/query_dispatch.rb

Overview

Story 9.4 (D2) — generates the INTERNAL dispatch controller backing the routes the ‘ruact_queries` macro draws: one controller subclass PER Query subclass, with one action per public query method. The per-class shape is what makes the AC4 callback opt-out scopable — a `ruact_skip_before_action` on one query class lands on that class’s controller only, and ‘only:`/`except:` options scope it further to individual query methods (each method is one action).

The controller inherits ‘Ruact.config.query_parent_controller` (default `ApplicationController`), resolved LAZILY here — at route-draw time, when the host’s constants exist — never at gem-load or configure time. The host’s REAL callback chain therefore runs before the query class is instantiated (FR89). The dev never sees this controller; it is named under this module (e.g. ‘Ruact::ServerFunctions::QueryDispatch::CatalogQueryController`) only so Rails’ string-based route resolution (‘to: “…/catalog_query#categories”`) and `rails routes` output stay legible.

Regeneration is idempotent: every ‘ruact_queries` evaluation (boot AND every dev-mode routes reload) rebuilds the constant from the query class’s CURRENT state, and the query class itself is re-constantized per request, so code reloading never serves a stale class.

Defined Under Namespace

Modules: Dispatching

Class Method Summary collapse

Class Method Details

.controller_for(query_class) ⇒ Class

Builds (or rebuilds) the dispatch controller for query_class and installs it under this module’s namespace, where the route target string from route_target_for resolves to it.

Parameters:

  • query_class (Class)

    a Query subclass

Returns:

  • (Class)

    the generated controller

Raises:



91
92
93
94
95
96
97
# File 'lib/ruact/server_functions/query_dispatch.rb', line 91

def controller_for(query_class)
  *namespace_segments, base = constant_segments(query_class)
  namespace = ensure_namespace(namespace_segments)
  const_name = "#{base}Controller"
  namespace.send(:remove_const, const_name) if namespace.const_defined?(const_name, false)
  namespace.const_set(const_name, build_controller(query_class))
end

.route_target_for(query_class) ⇒ String

The ‘to:` route target for query_class’s generated controller —the underscored constant path Rails camelizes back at dispatch time. The query class’s namespace is PRESERVED (review round 4): a nested path, never flattened, so two classes whose names differ only in namespace boundary (‘Admin::CatalogQuery` vs `AdminCatalogQuery`) map to DISTINCT controllers and can never cross-wire — collision is impossible by construction, across any number of RouteSets / engines.

Parameters:

  • query_class (Class)

    a Query subclass

Returns:

  • (String)

    e.g. ‘“ruact/server_functions/query_dispatch/admin/catalog_query”`



109
110
111
# File 'lib/ruact/server_functions/query_dispatch.rb', line 109

def route_target_for(query_class)
  "ruact/server_functions/query_dispatch/#{path_segments(query_class).join('/')}"
end