Class: Ecoportal::API::GraphQL::Model::Template::Instance

Inherits:
Object
  • Object
show all
Defined in:
lib/ecoportal/api/graphql/model/template/instance.rb

Overview

The mutable, in-memory template: Model::Template.load(client, id:) returns one of these. Owns the placeholder counters every Node mints from (see Node#placeholder — keeping them on the Instance rather than globally means two Instances loaded in the same process never share a counter, so specs get deterministic ph_sec_1-style ids per fixture without any manual reset).

THE THREE LINES (see the internal design doc, section 2.4):

template = Ecoportal::API::GraphQL::Model::Template.load(client, id: page_id)
template.fields.each { |f| f.label = "#{f.label} (reviewed)" }
template.save!(client)

#save! defaults to simulate: true (see its own doc) — nothing is sent to the server until the caller explicitly asks for simulate: false.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id:, patch_ver:, stages: [], phased: false) ⇒ Instance



30
31
32
33
34
35
36
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 30

def initialize(id:, patch_ver:, stages: [], phased: false)
  @id        = id
  @patch_ver = patch_ver
  @stages    = stages
  @phased    = phased
  @counters  = Hash.new(0)
end

Instance Attribute Details

#id ⇒ Object (readonly)

Returns the value of attribute id.



22
23
24
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 22

def id
  @id
end

#patch_ver ⇒ Object (readonly)

Returns the value of attribute patch_ver.



22
23
24
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 22

def patch_ver
  @patch_ver
end

#phased ⇒ Object (readonly) Also known as: phased?

Returns the value of attribute phased.



22
23
24
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 22

def phased
  @phased
end

#stages ⇒ Object (readonly)

Returns the value of attribute stages.



22
23
24
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 22

def stages
  @stages
end

Class Method Details

.from_doc(page) ⇒ Object

Builds an Instance from an already-fetched page doc (same shape Read.call returns) — used by both .load and StagedExecutor's between-phase re-reads, so both paths build the SAME tree shape from the SAME doc reader.



56
57
58
59
60
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 56

def from_doc(page)
  instance = new(id: page['id'], patch_ver: page['patchVer'], phased: page['__typename'] == 'PhasedPage')
  Read.stages(page).each { |stage_doc| instance.stages << build_stage(instance, stage_doc) }
  instance
end

.load(client, id:) ⇒ Object



48
49
50
51
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 48

def load(client, id:)
  page = Read.call(client, id)
  from_doc(page)
end

Instance Method Details

#as_commands ⇒ Object

The public diff engine — see CommandSynthesis's own doc for ordering/safety.



125
126
127
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 125

def as_commands
  CommandSynthesis.new(self).commands
end

#dirty? ⇒ Boolean



129
130
131
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 129

def dirty?
  !as_commands.empty?
end

#fields ⇒ Object

Every (non-removed) field across every stage, document order.



112
113
114
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 112

def fields
  stages.flat_map(&:fields)
end

#forces ⇒ Object



120
121
122
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 120

def forces
  stages.flat_map(&:forces)
end

#next_placeholder(prefix) ⇒ Object



40
41
42
43
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 40

def next_placeholder(prefix)
  @counters[prefix] += 1
  "ph_#{prefix}_#{@counters[prefix]}"
end

#save!(client = nil, simulate: true, chunk_size: StagedExecutor::DEFAULT_CHUNK_SIZE) ⇒ StagedExecutor::Plan, StagedExecutor::Result



139
140
141
142
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 139

def save!(client = nil, simulate: true, chunk_size: StagedExecutor::DEFAULT_CHUNK_SIZE)
  executor = StagedExecutor.new(self, client: client, chunk_size: chunk_size)
  simulate ? executor.plan : executor.execute!
end

#sections ⇒ Object



116
117
118
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 116

def sections
  stages.flat_map(&:sections)
end

#verify(client) ⇒ Hash

Re-reads the template fresh and reports, per node this Instance currently holds (and is not flagged removed), whether the live server agrees with THIS model's own current in-memory state. Call after a save!(simulate: false) — compares against the model's post-save state, not the pre-save snapshot, so a call with zero pending changes never reports a false "verified" for something it never actually checked (every tracked node is still compared, changed or not).



156
157
158
159
160
161
162
163
# File 'lib/ecoportal/api/graphql/model/template/instance.rb', line 156

def verify(client)
  live = Instance.load(client, id: id)
  report = { verified: [], mismatch: [], missing: [] }
  verify_fields(live, report)
  verify_options(live, report)
  verify_sections(live, report)
  report
end