-
Notifications
You must be signed in to change notification settings - Fork 18
Intake Structure Renderer
The intake structure renderer is a Rails console add-on that generates and formats a quick overview of any intake-related model, inspired by the structure_render
method for appeal task trees.
There are two ways to call the renderer, depending on your preference for convenience or distaste of monkey-patching.
> # the one-liner method
> puts IntakeRenderer.render(hlr)
>
> # monkey-patching makes multiple calls more convenient
> IntakeRenderer.patch_intake_classes
> puts hlr.render_intake
> puts hlr.veteran.render_intake
By default, PII is omitted from the rendered output, but it can be included explicitly:
> puts IntakeRenderer.render(hlr, show_pii: true)
> puts hlr.render_intake(show_pii: true)
Some sample output:
EndProductEstablishment 2393 (030HLRR, mod: 030, RFD)
├── Claim 600190553
├── RequestIssue 4765 (compensation, rating)
│ ├── descr: Service connection for PTSD is granted with an evaluat…
│ ├── Contention 348223
│ └── history:
│ ├── 2020-05-15 14:32:09 -0400: created
│ └── 2020-05-15 14:32:24 -0400: rating issue associated
├── history:
│ ├── 2020-05-15 14:32:09 -0400: created
│ ├── 2020-05-15 14:32:20 -0400: established
│ └── 2020-08-12 17:28:37 -0400: last synced: RFD
└── breadcrumbs:
├── HigherLevelReview 2425 (rcvd 2020-05-15, 93ab2535-0c78-46a9-8c8e-ae5b659e7973)
└── Veteran 2622 (PID: 600320726)
Although the intake data model is much more heterogenous and irregular than a task tree, there is nevertheless a loose hierarchy of objects "owning" other objects, which this renderer makes use of. The breadcrumbs section at the end of the output provides broader context for the rendered object, and always leads back to a veteran.
The code lives almost entirely in the IntakeRenderer class, which is a helper library; the Rails console loads it when starting up, but it's never called by the core app code.
Since simple recursion doesn't work for heterogenous types, each supported intake class is responsible for implementing a few methods (details
, children
, context
) that determine how its instances will be rendered. This pattern is essentially polymorphism, where various types adhere to a common interface, and supply type-specific behavior on how to be a node in a tree.
However, rather than defining renderer-specific methods in the actual Caseflow Intake classes and polluting their method namespaces, all methods live in IntakeRenderer instead. Polymorphic method dispatch therefore requires a bit of cleverness: method names are prepended with the snake-cased class name. For example, RequestIssue's methods are simply named request_issue_details
, request_issue_children
, and request_issue_context
.
The *_details
method returns a list of short tag-like descriptions for the object. The renderer uses these, along with the object's class and database ID, to format a one-line label for the object:
ClassName 123 (detail 1, detail 2, detail 3)
This label is returned by IntakeRenderer#label
and is useful in many contexts, e.g. when non-hierarchically related to another intake object, or as a breadcrumb.
If the details method is not implemented, the resulting label will have its parenthetical portion omitted.
The *_children
method returns a list of child nodes for the object. Child nodes are represented either as strings (for a leaf child with a label) or a
{"label": [recursive, child, nodes]}
hash, according to the input type expected by the underlying TTY::Tree library. This recursion is commonly done by calling IntakeRenderer#structure
on other Caseflow Intake objects.
If the method is not implemented, the object will be rendered as a leaf node.
The *_context
method returns a Caseflow Intake object that could be considered the parent or "owner" of the argument object. The breadcrumbs list is calculated by following the chain of parents, usually back to a Veteran.
Other than for Veteran, this method can be left un-implemented for types that are useful as a child node but don't have a single parent node, e.g. an intake User is responsible for many intakes. The renderer's tree hierarchy is an approximation, after all.
Outside of improving and fleshing out the existing renderer implementations, there are types that are not yet supported, including
- DecisionDocument
- BoardGrantEffectuation
as well as entire regions of the codebase that could benefit from structural clarity (RAMP reviews, perhaps?)
To add support for a new type, just add its class name to the RENDERABLE_CLASSNAMES
list at the top, and implement whichever of the three aforementioned polymorphic methods are applicable.
- Home
- Acronyms and Glossary
- Caseflow products
- Caseflow Intake
- Caseflow Queue
- Appeals Consumer
- Caseflow Reader
- Caseflow eFolder
- Caseflow Hearings
- Caseflow Certification
- Caseflow APIs
- Appeal Status API
- Caseflow Dispatch
-
CSUM Roles
- System Admin
- VHA Team Management
- Active Record Queries Resource
- External Integrations
- Caseflow Demo
- Caseflow ProdTest
- Background
- Stuck Jobs
- VA Notify
- Caseflow-Team
- Frontend Best Practices
- Accessibility
- How-To
- Debugging Tips
- Adding a Feature Flag with FeatureToggle
- Editing AMA issues
- Editing a decision review
- Fixing task trees
- Investigating and diagnosing issues
- Data and Metric Request Workflow
- Exporting and Importing Appeals
- Explain page for Appeals
- Record associations and Foreign Keys
- Upgrading Ruby
- Stuck Appeals
- Testing Action Mailer Messages Locally
- Re-running Seed Files
- Rake Generator for Legacy Appeals
- Manually running Scheduled Jobs
- System Admin UI
- Caseflow Makefile
- Upgrading Postgresql from v11.7 to v14.8 Locally
- VACOLS VM Trigger Fix M1
- Using SlackService to Send a Job Alert
- Technical Talks