Module: Hecks::Bluebook::Behaviour::Aggregate
- Includes:
- Identified, Indexed, Owns
- Included in:
- Aggregate
- Defined in:
- lib/hecks/bluebook/behaviour/aggregate.rb
Overview
WHAT AN AGGREGATE DOES, as opposed to what it holds.
The holding half — the field list, the readers, the emission — is
the same list the language already declares in
language/bluebook/aggregate.bluebook, said a second and third
time in Ruby. This half is not: derived identity, the name
indexes, the owner stamping and the finders are decisions about
HOW the declared shape is used, and no grammar states them.
Split so the holding half can be generated from the language without any of this being in the blast radius of a regeneration. Everything here is hand-written and permanent.
The three traits are shared with Entity (and, for Indexed,
with Command and PortOperation) — see behaviour/traits.rb on why
they are one module rather than four copies.
Instance Method Summary collapse
-
#add_port(port) ⇒ Object
A PORT IS DECLARED IN THE HECKSAGON, NOT THE BLUEBOOK — the boundary between the domain and its adapters, in hexagonal terms, is exactly what a
.hecksagonfile already IS for every other port (persistence, projection, ...). -
#hecks_separator ⇒ Object
An aggregate is a MEMBER of its chapter's namespace — "Pizzas::Pizza" — where everything else is declared ON its owner and joins with ".".
- #index_declarations ⇒ Object
- #port(named) ⇒ Object
- #projected_field(named) ⇒ Object
-
#settle ⇒ Object
THE HOOK THE GENERATED CONSTRUCTOR CALLS once every declared field is assigned.
- #storage_name ⇒ Object
-
#value_object(named) ⇒ Object
A value object is a CLASS now, so
nameis Ruby's answer (the constant path) and the declared name ishecks_name.
Methods included from Owns
Methods included from Indexed
#attribute, #command, #index_attributes, #index_by_hecks_name, #query
Methods included from Identified
Instance Method Details
#add_port(port) ⇒ Object
A PORT IS DECLARED IN THE HECKSAGON, NOT THE BLUEBOOK — the
boundary between the domain and its adapters, in hexagonal terms,
is exactly what a .hecksagon file already IS for every other
port (persistence, projection, ...). So this attaches AFTER the
aggregate already exists and is registered — HecksagonBuilder
calls it once per port declaration, having already stamped each
operation's reference attributes with declared_in = self, since
nothing upstream of a hecksagon load does that for it.
74 75 76 77 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 74 def add_port(port) @ports << port @ports_by_name[port.name] = port end |
#hecks_separator ⇒ Object
An aggregate is a MEMBER of its chapter's namespace — "Pizzas::Pizza" — where everything else is declared ON its owner and joins with ".".
29 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 29 def hecks_separator = "::" |
#index_declarations ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 43 def index_declarations index_attributes(@attributes) @value_objects_by_name = index_by_hecks_name(@value_objects) @commands_by_name = index_by_hecks_name(@commands) @queries_by_name = index_by_hecks_name(@queries) @ports_by_name = @ports.to_h { |port| [port.name, port] } # S12, ADR 0025 — keyed by SYMBOL, the same convention # `Indexed#attribute` already uses; `GuardState` asks for one # by name at every dispatch, the rebuild sweep walks all of # them once per pass. @projected_fields_by_name = @projected_fields.to_h { |field| [field.name, field] } end |
#port(named) ⇒ Object
64 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 64 def port(named) = @ports_by_name[named.to_s] |
#projected_field(named) ⇒ Object
56 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 56 def projected_field(named) = @projected_fields_by_name[named.to_sym] |
#settle ⇒ Object
THE HOOK THE GENERATED CONSTRUCTOR CALLS once every declared field is assigned. Nothing here is derivable from the declaration, which is exactly why it is not generated.
34 35 36 37 38 39 40 41 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 34 def settle derive_identity index_declarations # An entity stamps its own commands and queries when it is # declared, so the chain closes downward from here. stamp(@commands, @value_objects, @entities, @queries) self end |
#storage_name ⇒ Object
79 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 79 def storage_name = Naming.snake(@name) |
#value_object(named) ⇒ Object
A value object is a CLASS now, so name is Ruby's answer (the constant
path) and the declared name is hecks_name. This finder is on its way
out — once an attribute's type IS the class there is nothing to find —
but every consumer still asks by type string, so it stays until they
stop.
63 |
# File 'lib/hecks/bluebook/behaviour/aggregate.rb', line 63 def value_object(named) = @value_objects_by_name[named.to_s] |