Class: Ecoportal::API::GraphQL::Base::Page::DataField::Collection

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ecoportal/api/graphql/base/page/data_field/collection.rb

Overview

Wraps an array of raw data field docs as typed DataField objects. Provides v2-compatible access patterns used in eco-helpers scripts: components.get_by_type(:plain_text) — filter by field type components.get_by_name('FieldLabel') — find by label components.doc — raw doc array components.dirty_inputs — changed field hashes for mutation

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields) ⇒ Collection

Accepts raw field docs (→ built via from_doc) OR already-built DataField objects (kept as-is). Preserving existing objects lets a phased page's Stage#components share the SAME field objects as the page's canonical field_collection (so stage-level mutations land in the page's data_fields_updates — phased write-path identity).



16
17
18
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 16

def initialize(fields)
  @fields = Array(fields).map { |f| f.is_a?(DataField) ? f : DataField.from_doc(f) }
end

Class Method Details

.from_doc(raw_array) ⇒ Object

Build from a raw docs array.



21
22
23
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 21

def self.from_doc(raw_array)
  new(Array(raw_array))
end

Instance Method Details

#add(doc: nil, id: nil, label: nil, type: nil, **opts) {|field| ... } ⇒ Object

Add a new field to this collection (v2 compat: components.add). The field must reference an existing server-side ID (from buildFromTemplate). Yields the new field object to the block for configuration. Returns the field object.

Usage: components.add(doc: raw_doc) { |f| f.value = 'X' } components.add(id: 'f1', label: 'Name', type: 'PlainText') { |f| f.value = 'X' }

Yields:

  • (field)


60
61
62
63
64
65
66
67
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 60

def add(doc: nil, id: nil, label: nil, type: nil, **opts)
  raw = doc || opts.merge('id' => id, 'label' => label, '__typename' => type.to_s).compact
  field = DataField.from_doc(raw)
  @additions ||= []
  @additions << field
  yield field if block_given?
  field
end

#dirty?Boolean

Returns:

  • (Boolean)


92
93
94
95
96
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 92

def dirty?
  @fields.any?(&:dirty?) ||
    (@additions || []).any?(&:dirty?) ||
    !dirty_deletions.empty?
end

#dirty_additionsObject

Returns DataFieldInput hashes for fields added via #add.



83
84
85
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 83

def dirty_additions
  (@additions || []).filter_map(&:as_input)
end

#dirty_deletionsObject

Returns field IDs queued for deletion via #mark_for_deletion.



88
89
90
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 88

def dirty_deletions
  @deletions || []
end

#dirty_inputsObject

Returns DataFieldInput hashes for fields modified via value setters.



78
79
80
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 78

def dirty_inputs
  @fields.filter_map(&:as_input)
end

#docObject

Raw doc array (v2 compat — scripts iterate secs_doc / flds_doc).



48
49
50
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 48

def doc
  @fields.map(&:doc)
end

#each(&block) ⇒ Object



98
99
100
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 98

def each(&block)
  @fields.each(&block)
end

#empty?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 102

def empty?
  @fields.empty?
end

#get_by_id(id) ⇒ Object

Find a field by its id (v2 compat: components.get_by_id — used by e.g. event-changes / TnG cases that resolve a field by reference_id). Returns the field or nil.



42
43
44
45
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 42

def get_by_id(id)
  wanted = id.to_s
  @fields.find { |f| f.id.to_s == wanted }
end

#get_by_name(label, type: nil) ⇒ Object

Find first field matching label (case-insensitive). Optional type: restricts to that field type first (v2 compat: components.get_by_name(name, type:) — used by the farmers cutover use case which calls it directly, not via OozeRedirect).



35
36
37
38
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 35

def get_by_name(label, type: nil)
  pool = type ? get_by_type(type) : @fields
  pool.find { |f| f.label.to_s.downcase == label.to_s.downcase }
end

#get_by_type(type_key) ⇒ Object

Filter by field type. Accepts symbol (:plain_text), string ('PlainText'), or the GraphQL __typename directly. Matching is case-insensitive.



27
28
29
30
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 27

def get_by_type(type_key)
  target = normalise_type(type_key)
  @fields.select { |f| normalise_type(f.type) == target }
end

#lengthObject



106
107
108
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 106

def length
  @fields.length
end

#mark_for_deletion(id_or_field) ⇒ Object

Mark a field for deletion by field ID or field object. The field ID is sent in dataFields.deletions on the next update.



71
72
73
74
75
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 71

def mark_for_deletion(id_or_field)
  field_id = id_or_field.respond_to?(:id) ? id_or_field.id : id_or_field.to_s
  @deletions ||= []
  @deletions |= [field_id]
end