Class: Ecoportal::API::GraphQL::Base::Template::ChangeLogEntry
- Inherits:
-
Logic::BaseModel
- Object
- Common::Content::DoubleModel
- Common::GraphQL::Model
- Logic::BaseModel
- Ecoportal::API::GraphQL::Base::Template::ChangeLogEntry
- Defined in:
- lib/ecoportal/api/graphql/base/template/change_log_entry.rb
Overview
One entry of a TEMPLATE's change log — a single command the platform recorded against the template. Read-only.
── Where it comes from (verified in the Rails backend on 2026-08-19) ────────────
app/graphql/types/pages/template_type.rb declares
field :commands, Types::Pages::Interfaces::WorkflowCommandInterface.connection_type
and resolves it as
NewEp::Pages::Workflows::Commands::Base.where(page: object.page)
.from_template_builder.order(_id: :desc)
The narrow Template type itself is reachable as template { ... } on any page,
because app/graphql/types/pages/interfaces/base_page_interface.rb:27 declares
field :template, Types::Pages::TemplateType, null: true
── ★ TWO ACCESS CAVEATS — both are silent, neither raises ─────────────────────
commandsreturns nil, not an empty connection, unless the caller satisfiesPages::TemplatePolicy#update_information?(return unless allowed_to?(...)). A read-only account therefore sees NO change log and gets no error saying so. Treat a nil connection as "not permitted", never as "nothing changed".- The scope is
.from_template_builder— onlyTEMPLATE_BUILDER-sourced commands appear.WORKFLOW_BUILDERcommands against the same page are EXCLUDED (app/models/new_ep/pages/workflows/commands/base.rb,enum_field :feature_sourcewith values WORKFLOW_BUILDER / TEMPLATE_BUILDER). For the workflow-builder side of the same log seeQuery::PagesWorkflowCommands. Ordering is_id: :desc— newest first, server-side, not configurable.
── ★ WHY THIS LOG BEATS POLLING A WATERMARK ──────────────────────────────────
app/services/new_ep/pages/run_merged_forces.rb:17 writes with
@page.timeless.skip_patch_incr.rewrite(only_if: { updated_at: @page.updated_at.utc })
so a forces run bumps NEITHER patchVer NOR updatedAt. Any change tracker that
polls a watermark is structurally blind to force-driven change; the command log is
per-change and cannot be skipped that way.
(OPEN: whether forces run against TEMPLATES specifically is NOT confirmed — do not
assume either way.)
── Field set ─────────────────────────────────────────────────────────────────
These are the fields of the INTERFACE PagesWorkflowCommandInterface only
(app/graphql/types/pages/interfaces/workflow_command_interface.rb). The concrete
implementing types add their own (PagesWorkflowCommandChange.changes,
PagesWorkflowCommandChangeMessage.changeMessages,
PagesWorkflowCommandEsChange.changes); __typename is passed through so a caller
can branch, and those extras can be selected with an inline fragment or by reusing
Fragment :PagesWorkflowCommandFields.
Enum-valued fields are exposed as plain strings:
- commandAction: WorkflowCommandActionEnum
Direct Known Subclasses
Constant Summary collapse
- DETAIL_KINDS =
Which of the three concrete command types this entry is, as a symbol: :changes | :change_messages | :es_changes | nil (unknown/unselected
__typename). Use it instead of string-matching__typenameat call sites. { 'PagesWorkflowCommandChange' => :changes, 'PagesWorkflowCommandChangeMessage' => :change_messages, 'PagesWorkflowCommandEsChange' => :es_changes }.freeze
Constants included from Common::GraphQL::Model::Diffable
Common::GraphQL::Model::Diffable::DIFF_CLASS
Instance Method Summary collapse
-
#changes ⇒ Object
── What actually changed (only populated by the DETAIL selection) ────────── Present only when the node was selected with
Fragment :TemplateChangeLogEntryDetail(seeQuery::TemplateChangeLog.detail_block/api.template.change_log(detail: true)). -
#detail? ⇒ Boolean
True when this entry carries field-level detail.
- #detail_kind ⇒ Object
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
Instance Method Details
#changes ⇒ Object
── What actually changed (only populated by the DETAIL selection) ──────────
Present only when the node was selected with Fragment :TemplateChangeLogEntryDetail
(see Query::TemplateChangeLog.detail_block / api.template.change_log(detail: true)).
With the default light selection both readers are empty — empty means
"not selected", NOT "nothing changed", exactly like the nil-connection caveat above.
Deliberately raw hashes rather than a typed embed: the two changes-bearing types
do not share a shape (ChangeType.from/to are Strings;
StoredEsFilterChangeType.from/to are objects), so one typed model would have to
lie about one of them. This mirrors Base::PagesWorkflow::CommandChange#changes,
which does the same for the workflow-builder side of the same interface.
87 88 89 |
# File 'lib/ecoportal/api/graphql/base/template/change_log_entry.rb', line 87 def changes Array(doc['changes']) end |
#detail? ⇒ Boolean
True when this entry carries field-level detail. False both when the light selection was used and when a command genuinely recorded no changes -- those two are indistinguishable from the response alone, which is why the caller should know which selection it asked for.
110 111 112 |
# File 'lib/ecoportal/api/graphql/base/template/change_log_entry.rb', line 110 def detail? !changes.empty? || !changeMessages.to_a.empty? end |
#detail_kind ⇒ Object
102 103 104 |
# File 'lib/ecoportal/api/graphql/base/template/change_log_entry.rb', line 102 def detail_kind DETAIL_KINDS[__typename] end |