Module: Ecoportal::API::GraphQL::Model::Template::Node
- Defined in:
- lib/ecoportal/api/graphql/model/template/node.rb
Overview
Shared behaviour for every mutable node in the editable template tree (Stage, Section, Field, Option, Force, Binding, Helper). A node is either:
* LOADED — `id` is a real server id, carried in from `Read.call`. `snapshot`
freezes the mutable attributes as they were at load time, so `#dirty?` /
`#changed_attributes` can diff "now" against "as loaded" later.
* NEW — `id` is nil; the node was created in memory (`Stage#add_section`, etc.)
and has no server counterpart yet. `#ref` mints a client-chosen `placeholderId`
the first time it is asked (deterministic, `"ph_<prefix>_<n>"`, matching the
scheme `Builder::TemplateBuilder`/`Diff::CommandSynthesizer` already use,
counter owned by the root `Instance` so two loaded templates never share
counters) and memoises it — every command in the same `#as_commands` batch
that addresses this node reuses the SAME token.
#ref is the ONE thing every command-emission method should call to address a
node — never id directly — because it transparently upgrades from placeholder to
real id the moment StagedExecutor resolves this node against a live re-read
(#resolve!), without the caller needing to know which phase it is in.
Including class MUST define PLACEHOLDER_PREFIX (a short String, e.g. 'sec')
and #template (the root Instance, which owns the placeholder counters).
Instance Attribute Summary collapse
-
#id ⇒ Object
readonly
Returns the value of attribute id.
Instance Method Summary collapse
- #new? ⇒ Boolean
- #placeholder ⇒ Object
-
#ref ⇒ Object
The token every command that addresses this node must use: the real id once known, otherwise a memoised placeholder.
-
#remove! ⇒ Object
Flags this node for a
remove*command. - #removed? ⇒ Boolean
-
#resolve!(real_id) ⇒ Object
Called once a live re-read has matched this NEW node to its real server id.
Instance Attribute Details
#id ⇒ Object (readonly)
Returns the value of attribute id.
28 29 30 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 28 def id @id end |
Instance Method Details
#new? ⇒ Boolean
30 31 32 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 30 def new? id.nil? end |
#placeholder ⇒ Object
58 59 60 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 58 def placeholder @placeholder ||= template.next_placeholder(self.class::PLACEHOLDER_PREFIX) end |
#ref ⇒ Object
The token every command that addresses this node must use: the real id once
known, otherwise a memoised placeholder. StagedExecutor#resolve! is the only
code that ever calls #resolve! — everything downstream just calls #ref again
and transparently gets the real id from then on.
54 55 56 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 54 def ref id || placeholder end |
#remove! ⇒ Object
Flags this node for a remove* command. Only meaningful for a LOADED node — a
NEW node that is removed before ever being saved should simply be dropped from
its parent collection instead (there is nothing server-side to remove yet).
41 42 43 44 45 46 47 48 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 41 def remove! if new? raise ArgumentError, "#{self.class}: cannot remove a node that was never saved " \ '(drop it from its parent collection instead)' end @removed = true end |
#removed? ⇒ Boolean
34 35 36 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 34 def removed? !!@removed end |
#resolve!(real_id) ⇒ Object
Called once a live re-read has matched this NEW node to its real server id. Raises if called on an already-resolved node with a DIFFERENT id (a resolver bug, not a transient condition) — silently overwriting a resolved id would hide a mismatched cross-check upstream.
66 67 68 69 70 71 72 |
# File 'lib/ecoportal/api/graphql/model/template/node.rb', line 66 def resolve!(real_id) raise ArgumentError, "#{self.class}: resolve! requires a real id" if real_id.nil? return if id == real_id raise "#{self.class}: already resolved to #{id.inspect}, cannot re-resolve to #{real_id.inspect}" if id @id = real_id end |