Module: Hecks::Bluebook::Assembly::Build
- Defined in:
- lib/hecks/bluebook/assembly/build.rb
Overview
ONE WAY TO BUILD A CONSTRUCT, for every construct.
There used to be a method per category here — value_object(row),
command(row), policy(row) — each one gathering the same keywords the
contract already names. This reads the contract instead, so adding a field
to the language and forgetting to assemble it is caught by the coverage gate
rather than by nobody.
make is the only branch, and it is a real one: a construct that became a
class is .declared, an instance is .newed. That is the boundary
Query sits on, and it is a fact about Ruby rather than about the
domain.
Class Method Summary collapse
- .call(category, row, extra = {}) ⇒ Object
- .holder(contract) ⇒ Object
-
.read(reader, value) ⇒ Object
A reader is a Marks method, a list of them, or one of three spellings that need no decoding at all.
Class Method Details
.call(category, row, extra = {}) ⇒ Object
19 20 21 22 23 24 |
# File 'lib/hecks/bluebook/assembly/build.rb', line 19 def call(category, row, extra = {}) contract = Assembly.contract(category) keywords = contract.fields.to_h { |keyword, (key, reader)| [keyword, read(reader, row[key])] } holder(contract).public_send(contract.make, **keywords.merge(extra)) end |
.holder(contract) ⇒ Object
26 27 28 |
# File 'lib/hecks/bluebook/assembly/build.rb', line 26 def holder(contract) contract.holder or raise ArgumentError, "#{contract} holds nothing that can be built" end |
.read(reader, value) ⇒ Object
A reader is a Marks method, a list of them, or one of three spellings that need no decoding at all.
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/hecks/bluebook/assembly/build.rb', line 32 def read(reader, value) case reader when :plain then value when :identity then value&.to_sym when :flag then value ? true : false when Array # [:each, reader] maps a list ; [:option, name] reads one named option, # which needs its name as well as its value. reader.first == :each ? Array(value).map { |held| Marks.public_send(reader.last, held) } : Marks.option(reader.last, value) else Marks.public_send(reader, value) end end |