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

Methods included from Owns

#stamp

Methods included from Indexed

#attribute, #command, #index_attributes, #index_by_hecks_name, #query

Methods included from Identified

#derive_identity

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_separatorObject

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_declarationsObject



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]

#settleObject

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_nameObject



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]