Class: Hecks::Facade::Handle
- Inherits:
-
Object
- Object
- Hecks::Facade::Handle
- Defined in:
- lib/hecks/facade/handle.rb
Overview
ONE record in hand — the object Pizza.create_pizza(...) and
Pizza.find(id) give back.
ONE SHARED CLASS, not one minted per aggregate. The old door subclassed
Hecks::Aggregate per head and defined a reader per field ; this
wraps the same Runtime::Instance state hash and answers readers and
verbs through method_missing, closing over the dispatcher and the
aggregate's IR — so a boot mints no classes at all, and two boots in
one process each hand out handles bound to their own dispatcher.
A non-creating verb is a method returning self, so commands chain :
Pizza.create_pizza(...).add_topping(...).purchase(...)
Instance Attribute Summary collapse
-
#id ⇒ Object
readonly
Returns the value of attribute id.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
Equality is (WHICH AGGREGATE, WHICH ID) — two handles to the same record are the same record, and a Pizza never equals an Account that happens to share an id.
- #[](key) ⇒ Object
- #events ⇒ Object
- #fqn ⇒ Object
- #hash ⇒ Object
-
#initialize(dispatcher:, domain:, ir:, instance:) ⇒ Handle
constructor
A new instance of Handle.
- #inspect ⇒ Object (also: #to_s)
-
#method_missing(name, *args, **kwargs, &block) ⇒ Object
A declared field not yet written arrives here too (nil, the way a defined reader answered).
- #reload ⇒ Object
- #respond_to_missing?(name, include_private = false) ⇒ Boolean
-
#to_h ⇒ Object
id: @idLAST, not first — an aggregate is free to declare its own attribute literally namedid(BurningManPrep'sItem,attribute :id, ItemId, is real corpus now:identified_by :idreads THAT attribute for identity).
Constructor Details
#initialize(dispatcher:, domain:, ir:, instance:) ⇒ Handle
Returns a new instance of Handle.
21 22 23 24 25 26 27 28 29 |
# File 'lib/hecks/facade/handle.rb', line 21 def initialize(dispatcher:, domain:, ir:, instance:) @dispatcher = dispatcher @domain = domain @ir = ir @id = instance.id @state = instance.state define_reference_accessors define_verb_methods end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, **kwargs, &block) ⇒ Object
A declared field not yet written arrives here too (nil, the way a
defined reader answered). Verbs are NOT handled here — see
define_verb_methods for why.
75 76 77 78 79 |
# File 'lib/hecks/facade/handle.rb', line 75 def method_missing(name, *args, **kwargs, &block) return @state[name] if @state.key?(name) || reader?(name) super end |
Instance Attribute Details
#id ⇒ Object (readonly)
Returns the value of attribute id.
19 20 21 |
# File 'lib/hecks/facade/handle.rb', line 19 def id @id end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
Equality is (WHICH AGGREGATE, WHICH ID) — two handles to the same record
are the same record, and a Pizza never equals an Account that happens to
share an id. The old door said this with other.is_a?(self.class),
leaning on one class per aggregate ; the fqn says it in data.
62 |
# File 'lib/hecks/facade/handle.rb', line 62 def ==(other) = other.is_a?(Handle) && other.fqn == fqn && other.id == @id |
#[](key) ⇒ Object
31 |
# File 'lib/hecks/facade/handle.rb', line 31 def [](key) = @state[key.to_sym] |
#events ⇒ Object
48 49 50 |
# File 'lib/hecks/facade/handle.rb', line 48 def events @dispatcher.events.select { |event| event.aggregate == fqn && event.id == @id } end |
#fqn ⇒ Object
46 |
# File 'lib/hecks/facade/handle.rb', line 46 def fqn = "#{@domain}::#{@ir.hecks_name}" |
#hash ⇒ Object
64 |
# File 'lib/hecks/facade/handle.rb', line 64 def hash = [Handle, fqn, @id].hash |
#inspect ⇒ Object Also known as: to_s
66 67 68 69 |
# File 'lib/hecks/facade/handle.rb', line 66 def inspect fields = @state.map { |key, value| "#{key}=#{value.inspect}" }.join(" ") "#<#{@ir.hecks_name} #{@id} #{fields}>" end |
#reload ⇒ Object
52 53 54 55 56 |
# File 'lib/hecks/facade/handle.rb', line 52 def reload stored = repository.find(@id) @state = stored.state if stored self end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
81 82 83 |
# File 'lib/hecks/facade/handle.rb', line 81 def respond_to_missing?(name, include_private = false) @state.key?(name) || reader?(name) || super end |
#to_h ⇒ Object
id: @id LAST, not first — an aggregate is free to declare its own
attribute literally named id (BurningManPrep's Item, attribute :id, ItemId, is real corpus now: identified_by :id reads
THAT attribute for identity). When it does, @state[:id] holds the
full wrapped value object, not the bare identity string — merging
@state on top of { id: @id } let that wrapped VO silently
clobber the correct bare @id, so every caller of to_h (the JSON
door's own /api/:coll listing, in particular) got an object where
a plain identity string belonged. @id merged LAST always wins,
so to_h[:id] is always the true bare identity, regardless of
whether the aggregate also happens to declare a same-named field.
44 |
# File 'lib/hecks/facade/handle.rb', line 44 def to_h = @state.merge(id: @id) |