Class: Hecks::Bluebook::DSL::HecksagonBuilder
- Inherits:
-
Object
- Object
- Hecks::Bluebook::DSL::HecksagonBuilder
- Includes:
- WordGate
- Defined in:
- lib/hecks/bluebook/dsl/hecksagon_builder.rb
Constant Summary collapse
- GRAMMAR_CONTEXT =
"Hecksagon"
Constants included from WordGate
Class Attribute Summary collapse
-
.collector ⇒ Object
Returns the value of attribute collector.
Instance Attribute Summary collapse
-
#binds ⇒ Object
readonly
Returns the value of attribute binds.
-
#framework_members ⇒ Object
readonly
Returns the value of attribute framework_members.
-
#subscriptions ⇒ Object
readonly
Returns the value of attribute subscriptions.
-
#vendored_bluebooks ⇒ Object
readonly
Returns the value of attribute vendored_bluebooks.
Class Method Summary collapse
Instance Method Summary collapse
-
#build ⇒ Object
NO ungoverned-role check here anymore — see Registry::Verification#refuse_ungoverned_roles!.
-
#initialize(domain) ⇒ HecksagonBuilder
constructor
A new instance of HecksagonBuilder.
-
#method_missing(verb, *args, **kwargs, &block) ⇒ Object
DOMAIN-LEVEL DEFAULT BINDS —
persisted_by "Heki"bare, at the top of a hecksagon block, applies to every aggregate in this domain that doesn't declare its own override. -
#port_impl(name, &block) ⇒ Object
THE PRIMARY PORT, BARE AT THE ROOT — belongs to the CHAPTER as a whole, not one aggregate.
- #respond_to_missing?(_name, _include_private = false) ⇒ Boolean
-
#subscribe(event) ⇒ Object
An event this hecksagon takes from OUTSIDE the domain's own bluebook.
-
#uses_embryonaut_bluebook(name) ⇒ Object
A VENDORED, EXTERNAL bluebook this domain wants attached — same wiring-decision shape
uses_frameworkalready is, one level further out: not a member shipped inside hecks's own lib/, but a separate package (embryonaut_bluebooks) vendored into THIS project's own checkout. -
#uses_framework(name) ⇒ Object
A framework/ member this domain wants attached — Governance, Identity, whatever else lands beside them.
Constructor Details
#initialize(domain) ⇒ HecksagonBuilder
Returns a new instance of HecksagonBuilder.
16 17 18 19 20 21 22 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 16 def initialize(domain) @domain = domain @binds = [] @subscriptions = [] @framework_members = [] @vendored_bluebooks = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(verb, *args, **kwargs, &block) ⇒ Object
DOMAIN-LEVEL DEFAULT BINDS — persisted_by "Heki" bare, at the top
of a hecksagon block, applies to every aggregate in this domain
that doesn't declare its own override. Mirrors BindingProxy's own
method_missing one level down (aggregate: filled in there,
nil here) — generic over verb name, not hardcoded to
persisted_by/projected_by specifically, so any future verb
gets a domain-level default for free too. See Hecksagon#bind_for
for the fallback lookup this feeds.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 126 def method_missing(verb, *args, **kwargs, &block) # A closed-set grammar word (`port`, today) gets first refusal # — item #13's full metaprogrammed dispatch (slice 5); see # `WordGate#word_gate_dispatch`'s own header for why this class # needs to call it explicitly rather than including it the # ordinary way. Only once THAT says "not admitted" does the # genuinely open-ended `persisted_by "Heki"`-style bind # vocabulary below get a turn. result = word_gate_dispatch(verb, args, kwargs, block) return result unless result.equal?(WordGate::NOT_ADMITTED) return super unless args.first @binds << Bind.new(aggregate: nil, verb: verb.to_s, adapter: args.first.to_s, role: kwargs[:role]&.to_s) block&.call self end |
Class Attribute Details
.collector ⇒ Object
Returns the value of attribute collector.
11 12 13 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 11 def collector @collector end |
Instance Attribute Details
#binds ⇒ Object (readonly)
Returns the value of attribute binds.
14 15 16 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 14 def binds @binds end |
#framework_members ⇒ Object (readonly)
Returns the value of attribute framework_members.
14 15 16 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 14 def framework_members @framework_members end |
#subscriptions ⇒ Object (readonly)
Returns the value of attribute subscriptions.
14 15 16 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 14 def subscriptions @subscriptions end |
#vendored_bluebooks ⇒ Object (readonly)
Returns the value of attribute vendored_bluebooks.
14 15 16 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 14 def vendored_bluebooks @vendored_bluebooks end |
Class Method Details
.build(domain, &block) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 146 def self.build(domain, &block) builder = new(domain) resolver = ->(name) { BindingProxy.namespace(name, builder.binds) } previous = collector self.collector = builder.binds begin ConstShim.with(resolver) { builder.instance_eval(&block) } if block ensure self.collector = previous end builder.build end |
Instance Method Details
#build ⇒ Object
NO ungoverned-role check here anymore — see
Registry::Verification#refuse_ungoverned_roles!. Moved out of
per-block build, recovered alongside environment:
(Runtime::Loader.boot's comment has the provenance): a domain
split across multiple hecksagon blocks (base + an
environments/<name>.hecksagon overlay) would have every
block but the one declaring uses_framework "Governance"
refused HERE, even though Registry#add_hecksagon merges them
into one Hecksagon before anything ever dispatches against it.
Checking the MERGED result once, at verify! time — after every
file for this domain has loaded — is both more permissive (no
need to repeat uses_framework in every file) and strictly
more correct (a check against an incomplete, not-yet-merged
hecksagon can never see the real final shape).
113 114 115 116 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 113 def build Hecksagon.new(domain: @domain, binds: @binds, subscriptions: @subscriptions, framework_members: @framework_members, vendored_bluebooks: @vendored_bluebooks) end |
#port_impl(name, &block) ⇒ Object
THE PRIMARY PORT, BARE AT THE ROOT — belongs to the CHAPTER as a
whole, not one aggregate. BindingProxy#port is the aggregate-
scoped sibling (Payments::Payment.port("Gateway") do ... end);
this is what's left when a port isn't about any one record. The
bluebook must already be built and registered, since a hecksagon
loads after its bluebook, and this attaches to that real, final
object directly rather than building a second copy MetaValidator
would have to know how to reconstruct.
RENAMED FROM port — item #13's full metaprogrammed dispatch
(slice 5). Not bootstrap-reachable (checked directly — no
core/attached chapter declares a Hecksagon of its own). Reached
through WordGate#method_missing's new word_gate_dispatch,
called explicitly below since HecksagonBuilder's own
class-level method_missing (the open-verb catch-all beneath
this) always wins over the module's — see word_gate.rb's own
header for the full mechanism.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 77 def port_impl(name, &block) bluebook_ir = Hecks.current_registry.bluebook(@domain) or raise Malformed, "#{@domain} declares no such bluebook — a port needs one to belong to" # See BindingProxy#port's own comment on why this resolver swap is # needed — ConstShim's active resolver is one global for the whole # dynamic extent, currently this file's own BindingProxy-minting # one, which would turn a bare constant inside an operation's # `reference_to`/`attribute` into another BindingProxy instead of # a name. built = ConstShim.with(->(const) { const }) { DomainPortBuilder.build(name, &block) } # See BindingProxy#port's own comment on the same branch — a # `verb`-shaped port is a plain `Port`, registered the same # way `Hecks.port`'s top-level method already does, not attached # to this bluebook's own IR the way an operations-shaped # `DomainPort` is. return Hecks.current_registry.add_port(built) if built.is_a?(Port) bluebook_ir.add_port(built) end |
#respond_to_missing?(_name, _include_private = false) ⇒ Boolean
144 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 144 def respond_to_missing?(_name, _include_private = false) = true |
#subscribe(event) ⇒ Object
An event this hecksagon takes from OUTSIDE the domain's own bluebook.
26 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 26 def subscribe(event) = @subscriptions << event.to_s |
#uses_embryonaut_bluebook(name) ⇒ Object
A VENDORED, EXTERNAL bluebook this domain wants attached — same
wiring-decision shape uses_framework already is, one level
further out: not a member shipped inside hecks's own lib/,
but a separate package (embryonaut_bluebooks) vendored into THIS
project's own checkout. See EmbryonautBluebook's own header for
the full reasoning on why its ROOT can't be a fixed constant the
way Framework::ROOT is, and for the recovery provenance.
RECORDED ONTO @vendored_bluebooks, same shape uses_framework
already gives @framework_members — a SEPARATE list on purpose:
framework_members is load-bearing for refuse_ungoverned_roles!
(below) and for Governance's own attachment check; conflating
the two would make a vendored bluebook attachment satisfy a
Governance check it has nothing to do with.
56 57 58 59 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 56 def uses_embryonaut_bluebook(name) @vendored_bluebooks << name.to_s Hecks::EmbryonautBluebook.load!(name) end |
#uses_framework(name) ⇒ Object
A framework/ member this domain wants attached —
Governance, Identity, whatever else lands beside them.
Attaching one is a WIRING decision, the same kind persisted_by/
projected_by already are, so it lives here rather than as a
fact stated in the domain's own bluebook. Recorded onto THIS
hecksagon, the same way subscribe records onto its own
subscriptions — and loads the member's bluebook then its own
hecksagon into whatever registry this one is loading into, see
Framework.load!.
37 38 39 40 |
# File 'lib/hecks/bluebook/dsl/hecksagon_builder.rb', line 37 def uses_framework(name) @framework_members << name.to_s Hecks::Framework.load!(name) end |