Module: Eco::API::UseCases::GraphQL::Compat::OozeRedirect
- Defined in:
- lib/eco/api/usecases/graphql/compat/ooze_redirect.rb,
lib/eco/api/usecases/graphql/compat/ooze_redirect/dirty_array.rb,
lib/eco/api/usecases/graphql/compat/ooze_redirect/force_compat.rb,
lib/eco/api/usecases/graphql/compat/ooze_redirect/field_patches.rb
Overview
Transparently redirects an OozeSamples-based use case from the APIv2 ooze path to the GraphQL compat layer. Include it in the case class and nothing else needs to change in the script.
What it redirects
- Page iteration:
with_each_entryfetches viagraphql.pages.get api_v2/apiv2: returns the graphql compat clientstage(name): resolves viatarget.stages[name](GraphQL stage model)with_fields(ooz, label:, type:): reads fromooz.components(GraphQL)update_ooze(ooz): saves viagraphql.pages.updatetarget.submit!/target.sign_off!: captured and forwarded tographql.pages.update
What it patches (one-time, guarded)
- V2 type classes (
PlainTextField,SelectionField, etc.) recognise GraphQL instances incase/whendispatch via=== - GraphQL
Peoplefield:people_ids <<triggers dirty tracking - GraphQL
CrossReferencefield:add,clear,reference_ids - GraphQL
Selectfield:select,deselect,values,options(options returns Struct objects with.name/.value) - All GraphQL fields:
oozestub returns a minimal object for warning messages Interface::BasePage:submit!(stage_id:)queues a submit-only flag (completes the fill-in task);sign_off!(stage_id:)queues sign-off. Tasks are sequential (fill-in → review): sign-off on a not-yet-submitted stage submits + signs off in one go (completePageTask{ signOff: true }).submit!(force: true)maps to completePageTask{ forcedComplete: true } (admin/superuser; skips the required-field check).
Per-run debug logging
Each type of redirection logs once per run (not per page) at :debug level.
Filter with ECOPORTAL_LOG_LEVEL=debug or the session logger config.
Usage
class Custom::UseCase::TOOCSCoding < Eco::API::UseCases::OozeSamples::TargetOozesUpdateCase
include Eco::API::UseCases::GraphQL::Compat::OozeRedirect
# ... rest of class unchanged ...
end
Limitations
- Force / binding operations (
target.forces,force.bindings) are not available in GraphQL — those calls will raise NoMethodError. - Field property setters (
fld.label=,fld.required=) are template mutations; they are not supported and will raise NoMethodError. page_result.membranes(on PreviewPage search results) is not supported directly; use register search viagraphql.registers.searchinstead.
TODO: Force / binding support (blocked on GraphQL endpoint)
Engineering is working on exposing "legacy forces" via the GraphQL API.
Once that endpoint is available, extend this module with a ForceCompat
sub-module (same include pattern — nothing changes in end scripts) covering:
target.forces.get_by_name(name) → query forces by name on a page
force.bindings.get_by_name(name) → field bindings on a force
force.bindings.add(field, name:) → add a binding
force.bindings.delete!(binding) → remove a binding
force.custom_script → read the LISP script
force.custom_script = new_script → write the LISP script
force.script → raw script content (alias)
Affected cases currently blocked (from multi_org_api survey, ~50% of all ooze cases):
act-gov: 5 x 20240130_act_*_case, rearrage_page_sites_case
briscoes: remove_induction_sections, 310524_Briscoes_Remove_Tasks
chorus: 4 x audit_update cases
hcc: update_enterprise_risk_case
lic: update_life_cycle_force_case
mitre10: rich_text_update, update_location_force, updating_template
npdc: contractor_title_force, risk_titile_force, fix_title_syncing,
reminder_date_fields, 10092024_NPDC_CP_Add_Force
profile-group: int_training_review, 20231026_profile_wellness
turners-growers: event_changes, inj_cost_calc, remove_line_force
twg: hide_attached_risks, add_new_force
Implementation sketch (to be built when the endpoint lands):
module ForceCompat
# Patch GraphQL BasePage to respond to .forces
# Returns a proxy whose #get_by_name queries the GraphQL force endpoint
# and returns ForceProxy objects wrapping the response.
# ForceProxy exposes #bindings (BindingsProxy), #custom_script, #script.
# BindingsProxy exposes #get_by_name, #add, #delete!.
end
OozeRedirect.include(ForceCompat) # or extend OozeRedirect::FieldPatches
Defined Under Namespace
Modules: FieldPatches, ForceCompat, Infrastructure Classes: DirtyArray
Class Method Summary collapse
-
.force_support? ⇒ Boolean
Returns true when the installed ecoportal-api-graphql gem exposes Query::PageWithForces (the forces-aware page query).
- .included(base) ⇒ Object
Class Method Details
.force_support? ⇒ Boolean
Returns true when the installed ecoportal-api-graphql gem exposes
Query::PageWithForces (the forces-aware page query).
Forces are NOT usable on GraphQL yet: Query::PageWithForces is a WIP whose query
currently fails schema validation (selections on PageUnion; id on DataFieldBinding/
SectionBinding; unused ForceFields) and the backend forces endpoint is still in
progress. The class merely being defined is not a readiness signal — activating
ForceCompat on that basis makes EVERY OozeRedirect case fetch via the broken force
query (e.g. toocs, which doesn't even use forces). Keep OFF until forces actually
work; then restore a real readiness check.
120 121 122 |
# File 'lib/eco/api/usecases/graphql/compat/ooze_redirect.rb', line 120 def self.force_support? false end |
.included(base) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/eco/api/usecases/graphql/compat/ooze_redirect.rb', line 95 def self.included(base) FieldPatches.apply! # Provide `graphql` (lazy, memoized session.api(version: :graphql)) regardless of # the host's base class. OozeSamples cases (cans/toocs) don't include the GraphQL # helpers that Custom::UseCase paths pick up, yet Infrastructure#api_v2 / # #with_each_entry / #update_ooze all call `graphql` — without this they raise # NameError: undefined `graphql`. base.include(Eco::API::UseCases::GraphQL::Helpers::Base::GraphQLEnv) # Prepend Infrastructure first so it sits below ForceCompat in the MRO. # With Ruby's prepend, last-prepended wins — so ForceCompat::Infrastructure # must be prepended AFTER Infrastructure to be first in the lookup chain: # MRO: ForceCompat::Infrastructure → Infrastructure → base class base.prepend(Infrastructure) base.prepend(ForceCompat::Infrastructure) if force_support? end |