Class: Ecoportal::API::GraphQL::Base::PresetView
- Inherits:
-
Logic::BaseModel
- Object
- Common::Content::DoubleModel
- Common::GraphQL::Model
- Logic::BaseModel
- Ecoportal::API::GraphQL::Base::PresetView
- Defined in:
- lib/ecoportal/api/graphql/base/preset_view.rb
Overview
A register preset view — saved column/sort/filter configuration for previewPages.
Scripts use the id as presetViewId in register.previewPages queries.
Direct Known Subclasses
Constant Summary collapse
- DIFF_CLASS =
fieldConfigurationsis a passarray (leaf) invisible to the default DiffService; LeafDiffService detects it as a full-set replace, which is what makes a columns-only change reach#as_inputat all (before it, the array was dropped from the flat diff and no mutation was issued). The read-key/shape conversion that change then needs is handled below — the GAP-P1 that comment referred to as a separate pending converter is closed by it. See Diffable::LeafDiffService. Ecoportal::API::Common::GraphQL::Model::Diffable::LeafDiffService
- READ_KEY =
READ key vs WRITE key — and, on update, read SHAPE vs write SHAPE.
The API RETURNS the collection as
fieldConfigurations, a plain list (see thepassarraybelow — that stays as-is, consumers read it). The mutations call itfieldConfigs, and the two mutations do NOT agree on its shape. Schema-verified against the live introspection dump (20260730):CreatePresetViewInput.fieldConfigs : [FieldConfigurationInput!]! UpdatePresetViewInput.fieldConfigs : FieldConfigurationOneToManyInput! { additions:, deletions:, updates: }Both are NON_NULL with no default value — i.e. REQUIRED on every call — while the
FieldConfigurationOneToManyInputmembers each default to[], so{}is a valid no-op value for an update that does not touch the columns.Emitting the read key
fieldConfigurationsis an unknown-argument error, and emitting the read LIST underfieldConfigsis a type error: either one rejects the WHOLE mutation, aname-only edit included.#as_inputemits the UPDATE shape.Logic::Mutation#as_inputhands a read model straight tomodel.as_inputwithout telling it which mutation it feeds, and the only model-driven path isregister.preset_view.update: a read model carries anid, whichCreatePresetViewInputdoes not even accept. Create is built from a caller-supplied Hash (see Builder::Register::PresetView) whosefieldConfigsis already the plain array the schema wants — it needs no conversion. 'fieldConfigurations'.freeze
- FIELD_CONFIG_INPUT_KEYS =
The fields
FieldConfigurationInputaccepts (same dump). The read nodes also carry__typename— the read side is a union, see Fragment::FieldConfiguration — which the input type does NOT accept, so nodes are whitelisted through this list rather than passed along verbatim. %i[ id key name weight dataFieldLabel type showTime valueToShow mode displayUid ].freeze
Class Method Summary collapse
-
.build_update_input(model, input) ⇒ Hash?
Turns a raw mutation-input diff into a valid
UpdatePresetViewInput: drops the read key and setsfieldConfigsto the one-to-many delta. -
.field_config_input(node) ⇒ Hash
The node reduced to the keys
FieldConfigurationInputaccepts, symbol-keyed.
Instance Method Summary collapse
-
#as_input(target_class: nil, clientMutationId: '') ⇒ Object
Mutation input for this preset view, shaped for
updatePresetView. -
#field_configs_delta ⇒ Hash
The
FieldConfigurationOneToManyInputdelta between the server baseline (original_doc) and the currentdoc, matched on the configid:additions= nodes with no known id,deletions= baseline ids that are gone,updates= known nodes whose (input-visible) content changed.
Methods included from Concerns::SnakeCamelAccess
#method_missing, #respond_to_missing?
Methods included from Common::GraphQL::Model::AsInput
Methods included from Common::GraphQL::Model::Diffable
Methods included from Common::GraphQL::ClassHelpers
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Ecoportal::API::GraphQL::Concerns::SnakeCamelAccess
Class Method Details
.build_update_input(model, input) ⇒ Hash?
Turns a raw mutation-input diff into a valid UpdatePresetViewInput: drops the
read key and sets fieldConfigs to the one-to-many delta.
Idempotent — the read key is deleted and the delta is recomputed from
doc/original_doc, so a second application yields the same Hash. That is what
makes it safe for both seams (#as_input and Input::PresetView::Update .from_model) to call it on the same Hash.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/ecoportal/api/graphql/base/preset_view.rb', line 72 def build_update_input(model, input) return input unless model.respond_to?(:field_configs_delta) delta = model.field_configs_delta return input if input.nil? && delta.empty? input ||= {} input.delete(:fieldConfigurations) input.delete(READ_KEY) input[:id] ||= model.id if model.respond_to?(:id) input[:fieldConfigs] = delta input end |
.field_config_input(node) ⇒ Hash
Returns the node reduced to the keys FieldConfigurationInput accepts,
symbol-keyed. Keys the read selection did not ask for are simply absent.
89 90 91 92 93 94 95 |
# File 'lib/ecoportal/api/graphql/base/preset_view.rb', line 89 def field_config_input(node) FIELD_CONFIG_INPUT_KEYS.each_with_object({}) do |key, out| str = key.to_s out[key] = node[str] if node.key?(str) out[key] = node[key] if node.key?(key) end end |
Instance Method Details
#as_input(target_class: nil, clientMutationId: '') ⇒ Object
Mutation input for this preset view, shaped for updatePresetView.
127 128 129 130 131 132 133 134 135 |
# File 'lib/ecoportal/api/graphql/base/preset_view.rb', line 127 def as_input(target_class: nil, clientMutationId: '') input = self.class.build_update_input(self, super) return input if input.nil? || target_class # `super` merges it only when it built the Hash itself; a columns-only change # synthesises the Hash here, so keep the wire payload identical either way. input[:clientMutationId] = clientMutationId.to_s unless input.key?(:clientMutationId) input end |
#field_configs_delta ⇒ Hash
The FieldConfigurationOneToManyInput delta between the server baseline
(original_doc) and the current doc, matched on the config id:
additions = nodes with no known id, deletions = baseline ids that are gone,
updates = known nodes whose (input-visible) content changed. Empty members are
omitted, so an untouched collection yields {} — the valid no-op.
Computed DIRECTLY from the docs rather than from the flat diff, for the same
reason as Logic::Input::IdDiffFields: passarray leaves are dropped by the
cascaded DiffService.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/ecoportal/api/graphql/base/preset_view.rb', line 109 def field_configs_delta current = field_config_nodes(doc) original = field_config_nodes(original_doc) known = original.filter_map {|node| node[:id]} additions = current.reject {|node| node[:id] && known.include?(node[:id])} updates = (current - additions) - original deletions = known - current.filter_map {|node| node[:id]} {}.tap do |delta| delta[:additions] = additions unless additions.empty? delta[:deletions] = deletions unless deletions.empty? delta[:updates] = updates unless updates.empty? end end |