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)


53
54
55
56
57
58
59
60
# File 'lib/ecoportal/api/graphql/base/page/data_field/collection.rb', line 53

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)


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

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

#dirty_additionsObject

Returns DataFieldInput hashes for fields added via #add.



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

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

#dirty_deletionsObject

Returns field IDs queued for deletion via #mark_for_deletion.



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

def dirty_deletions
  @deletions || []
end

#dirty_inputsObject

Returns DataFieldInput hashes for fields modified via value setters.



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

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

#docObject

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



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

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

#each(&block) ⇒ Object



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

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

#empty?Boolean

Returns:

  • (Boolean)


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

def empty?
  @fields.empty?
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



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

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.



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

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