Class: Hecks::Bluebook::ReadModel
- Inherits:
-
QuerySpecification::ReadModel::Specification
- Object
- QuerySpecification::Common::Options
- QuerySpecification::ReadModel::Specification
- Hecks::Bluebook::ReadModel
- Includes:
- Behaviour::ReadModel, Construct, IR
- Defined in:
- lib/hecks/bluebook/read_model.rb
Overview
A read model — an ask that gathers heads from more than one aggregate.
Like a query it crosses over as an INSTANCE, and for the same reason: its
body is inherited from QuerySpecification::ReadModel::Specification, whose
readers the runtime and the SQLite adapter both call on the object. It gains
an identity and an owner ; it keeps the name it always had, because only a
CLASS ever had a competing answer for name.
Instance Attribute Summary collapse
-
#aggregate_heads ⇒ Object
readonly
Returns the value of attribute aggregate_heads.
-
#count ⇒ Object
readonly
Returns the value of attribute count.
-
#description ⇒ Object
readonly
Returns the value of attribute description.
-
#group_by ⇒ Object
readonly
Returns the value of attribute group_by.
-
#median_field ⇒ Object
readonly
Returns the value of attribute median_field.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#reference_name ⇒ Object
readonly
Returns the value of attribute reference_name.
-
#reference_target ⇒ Object
readonly
Returns the value of attribute reference_target.
Attributes included from Construct
#hecks_name, #hecks_owner, #hecks_root
Attributes inherited from QuerySpecification::ReadModel::Specification
Attributes inherited from QuerySpecification::Common::Options
#authorization, #cursor, #inspection, #limit, #null_semantics, #offset, #order_by, #wheres
Instance Method Summary collapse
-
#initialize(name:, description: nil, reference_name: nil, reference_target: nil, aggregate_heads: [], group_by: [], count: nil, median_field: nil, **options) ⇒ ReadModel
constructor
reference_name:/reference_target:are nil for a ROOTLESS read model (noreference_todeclared) —&.throughout, rather than the.to_s/.to_symthis used to require unconditionally, soreference_target.nil?stays a real, checkable fact for the interpreter instead of silently becoming"". -
#to_h ⇒ Object
wheres/order_by/limitare spelled explicitly here, the SAME mechanismQuery#to_halready uses (query.rb, read directly before this was written) — always present,wheresa (possibly empty) array andorder_by/limitnil when undeclared, exactly like a Query's.
Methods included from Behaviour::ReadModel
#count?, #filtered_head_name, #group_by_fields, #query_name
Methods included from IR
Methods included from Construct
#hecks_fqn, #hecks_root?, #hecks_separator
Methods inherited from QuerySpecification::Common::Options
#extra_options_to_h, #options_to_h
Constructor Details
#initialize(name:, description: nil, reference_name: nil, reference_target: nil, aggregate_heads: [], group_by: [], count: nil, median_field: nil, **options) ⇒ ReadModel
reference_name:/reference_target: are nil for a ROOTLESS read
model (no reference_to declared) — &. throughout, rather than
the .to_s/.to_sym this used to require unconditionally, so
reference_target.nil? stays a real, checkable fact for the
interpreter instead of silently becoming "".
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/hecks/bluebook/read_model.rb', line 37 def initialize(name:, description: nil, reference_name: nil, reference_target: nil, aggregate_heads: [], group_by: [], count: nil, median_field: nil, **) super(joins: aggregate_heads, **) @name = name.to_s @hecks_name = @name @description = description @reference_name = reference_name&.to_sym @reference_target = reference_target&.to_s @aggregate_heads = aggregate_heads # Hash rows (`{field: :agg}`), same shape as `aggregate_heads` — # `group_by_fields` is the convenience reader everything but # `to_h`/the Judge's own generic walk actually wants. @group_by = group_by # ABSENT IS NOT FALSE. `@count` stays nil rather than becoming # `false` when undeclared — the same "if you declare it, declare # something" reading `Lifecycle`'s own optional fields rely on # (MetaValidator::Judge#setters skips a setter whose every # source is `nil`, so an ALWAYS-false `@count` would dispatch # `ReadModel.Count` on every read model that never wrote the # word at all). `!!count` collapses a truthy DSL `true` (or a # reconstructed `true`) to the same `true`/`nil` pair either path # produces — never `false`. @count = count ? true : nil @median_field = median_field&.to_sym end |
Instance Attribute Details
#aggregate_heads ⇒ Object (readonly)
Returns the value of attribute aggregate_heads.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def aggregate_heads @aggregate_heads end |
#count ⇒ Object (readonly)
Returns the value of attribute count.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def count @count end |
#description ⇒ Object (readonly)
Returns the value of attribute description.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def description @description end |
#group_by ⇒ Object (readonly)
Returns the value of attribute group_by.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def group_by @group_by end |
#median_field ⇒ Object (readonly)
Returns the value of attribute median_field.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def median_field @median_field end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def name @name end |
#reference_name ⇒ Object (readonly)
Returns the value of attribute reference_name.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def reference_name @reference_name end |
#reference_target ⇒ Object (readonly)
Returns the value of attribute reference_target.
29 30 31 |
# File 'lib/hecks/bluebook/read_model.rb', line 29 def reference_target @reference_target end |
Instance Method Details
#to_h ⇒ Object
wheres/order_by/limit are spelled explicitly here, the SAME
mechanism Query#to_h already uses (query.rb, read directly
before this was written) — always present, wheres a (possibly
empty) array and order_by/limit nil when undeclared, exactly
like a Query's. extra_options_to_h still excludes these three by
name (options.rb), so nothing here double-spells them; the two
constructs now share one encoding for the same three words rather
than a reader needing to learn a second one. See this file's own
filtered_head_name and language/bluebook/syntax.bluebook's
ReadModel where/order_by/limit member rows for the history
of why this WAS narrower, and 2026-08-11's read-model where/
order_by/limit task for why it stopped being.
Same dynamic tail as a Query's, plus two collections whose
ROWS are plain hashes rather than constructs — they are
normalised here rather than by many, which recurses through
to_h and would have nothing to call.
count/median_field are ABSENT (no key at all), not nil,
when undeclared — unlike group_by (always a [], never
missing) they are the FIRST fields this construct has ever
added that no OLDER real corpus member could possibly carry, so
merging them unconditionally would have put a null onto every
existing read model's own wire shape (banking's
ComplianceDashboard/CustomerPortfolio, the language's own
WholeBluebook, ...) for a fact nothing about them changed —
the exact extra_options_to_h reads for cursor/offset/etc,
applied here for the same reason.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/hecks/bluebook/read_model.rb', line 97 def to_h reductions = {} reductions[:count] = true if @count reductions[:median_field] = @median_field.to_s if @median_field super .merge(aggregate_heads: @aggregate_heads.map { |head| head.merge(as: head[:as].to_s) }) .merge(group_by: @group_by.map { |row| row.merge(field: row[:field].to_s) }) .merge(reductions) .merge() end |