Class: Hecks::Bluebook::MetaValidator::Plan
- Inherits:
-
Object
- Object
- Hecks::Bluebook::MetaValidator::Plan
- Defined in:
- lib/hecks/bluebook/meta_validator/plan.rb
Overview
What the language says about ITSELF, read back as something walkable.
The judge used to carry one hand-written branch per category, and the reason given for keeping it that way was that "which append command belongs to which list is not derivable from a name". True — and beside the point. It is derivable from the language's own IR, because every append command DECLARES its target:
command "Argument" do
reference_to Command
then_set :arguments, append: { name: :name, type: :type, ... }
end
That one line says both things a walk needs: Command.Argument is the
appender for the arguments list, and the map binds each value-object
field to the command argument that fills it. Nothing is matched by name.
The same reading recovers the containment tree. A command with NO
self-reference is the creating one, and the *_id argument it carries
names the parent — so Bluebook -> Aggregate -> Command / ValueObject /
Query / Entity, ValueObject -> Member, ProcessManager -> Handler ->
Dispatch all fall out of the declarations rather than being restated here.
Usage:
plan = Plan.for(MetaValidator.grammar_registry)
plan.category("Command").parent # => "Aggregate"
plan.category("Command").appends["rules"] # => Append(verb: "Rule", map: {...})
plan.verbs # every Bluebook:: verb declared
This reads the language. It does not read a bluebook and it dispatches nothing — that is the judge's job.
Defined Under Namespace
Classes: Append, Category, Setter
Instance Attribute Summary collapse
-
#categories ⇒ Object
readonly
Returns the value of attribute categories.
Class Method Summary collapse
Instance Method Summary collapse
- #category(name) ⇒ Object
-
#initialize(meta) ⇒ Plan
constructor
A new instance of Plan.
- #names ⇒ Object
-
#verbs ⇒ Object
Every verb the language declares, spelled as the judge would dispatch it.
Constructor Details
#initialize(meta) ⇒ Plan
Returns a new instance of Plan.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/hecks/bluebook/meta_validator/plan.rb', line 73 def initialize() @categories = {} .aggregates.each do |aggregate| # Vocabulary declares no commands — it is static declaration read from # the IR by spec/vocabulary_conformance_spec, never dispatched. It needs # no special case: a category with nothing to offer contributes nothing. next if aggregate.commands.empty? @categories[aggregate.hecks_name] = read(aggregate) # S17, ADR 0026 — Member/Handler/Dispatch are ENTITIES now # (`entity "Member" do ... end`, nested under `ValueObject`/ # `ProcessManager`/`Handler`), not their own top-level # aggregates — so `meta.aggregates` alone no longer finds # them the way it always found a standalone `aggregate # "Member"`. Each STILL needs its own named category here: # `Assembly::Contracts` keeps a bespoke entry for each # (Member's own open-map `pairs`, Dispatch's own open-map # `with_spec`), distinct from the single generic "Entity" # category every ORDINARY real-corpus entity (LedgerEntry, # Withdrawal, ...) is described through instead. Safe to # walk EVERY meta-domain aggregate's own `.entities` # unconditionally — `Plan` only ever reads the META- # DOMAIN'S OWN self-description (`Plan.for(MetaValidator. # grammar_registry)`), which never declares a generic, # nameless entity of its own the way a REAL domain's # `LedgerEntry` is; the only entities the meta-domain # itself ever declares are exactly the three this ADR # names. `entity_owned: true` records WHY this is a # category at all — the real runtime has no top-level # aggregate named "Member" to dispatch a BARE verb into # any more, so the judge has to build a DOTTED one instead # (see `Judge#verb_for`). # # RECURSES — `Dispatch` nests inside `Handler`, which nests # inside `ProcessManager`, two levels deep, not one. Each # nested entity's own `parent` names the DIRECT owner it was # actually found under (Dispatch's is "Handler", not # "ProcessManager") — `read`'s own `owner:` argument already # takes whichever name is passed, so walking one level deeper # each recursive call is the whole change; nothing about # `read` itself needed to know how deep it was called from. add_nested_entities(aggregate) end @categories.freeze end |
Instance Attribute Details
#categories ⇒ Object (readonly)
Returns the value of attribute categories.
71 72 73 |
# File 'lib/hecks/bluebook/meta_validator/plan.rb', line 71 def categories @categories end |
Class Method Details
.for(registry) ⇒ Object
67 68 69 |
# File 'lib/hecks/bluebook/meta_validator/plan.rb', line 67 def self.for(registry) new(registry.bluebook("Bluebook")) end |
Instance Method Details
#category(name) ⇒ Object
120 |
# File 'lib/hecks/bluebook/meta_validator/plan.rb', line 120 def category(name) = @categories[name.to_s] |
#names ⇒ Object
121 |
# File 'lib/hecks/bluebook/meta_validator/plan.rb', line 121 def names = @categories.keys |
#verbs ⇒ Object
Every verb the language declares, spelled as the judge would
dispatch it. S17, ADR 0026 — an ENTITY-OWNED category (its
own entity_owned flag) has no real top-level aggregate the
runtime can route a BARE verb into any more, so it is
spelled DOTTED here too — Bluebook::ValueObject.Member. Declare, Bluebook::ProcessManager.Handler.Dispatch.Bind —
matching Judge#verb_for/#dotted_prefix's own build
exactly (recursing the same way, for the same reason: an
entity-owned category's own parent may itself be entity-
owned), so this stays what it already is: the judge's own
coverage promise, not a second guess at it.
134 135 136 137 138 |
# File 'lib/hecks/bluebook/meta_validator/plan.rb', line 134 def verbs @categories.flat_map do |name, category| category.verbs.map { |verb| "Bluebook::#{dotted_prefix(name)}.#{verb}" } end end |