Skip to content

Conversation

@ChrisBAshton
Copy link
Contributor

@ChrisBAshton ChrisBAshton commented Jan 6, 2026

What

WIP: exploring what it would look like to do the entire refactor in one PR, as opposed to PR 10965 which explores rolling it out in stages.

This PR refactors the schema design for config-driven document types by separating concerns that were previously conflated under edit_screens. We now:

  • removed settings.edit_screens, in favour of a new top-level forms hash. It describes things at the UI level: which fields appear on which forms.
  • adds new top-level presenters field, describing which field values get sent to Publishing API (and how to map them)
  • removes schema.properties in favour of schema.attributes: effectively a slimmed down version of the former.
  • schema.validations remains unchanged, but we no longer have 'nested' validation (e.g. schema.properties.duration.validations) - the 'nested' validation has moved up into the schema.validations (in this example, schema.validations.duration). This isn't represented in the overview below as we only had one example and it's more of a side-effect than a deliberate change.

Overview of schema changes:

"schema": {
-  "properties": {
-    "body": {
-      "title": "Body",
-      "type": "string",
-      "format": "govspeak"
-    }
+  "attributes": {
+    "body": {
+      "type": "string",
+    }
+  }
}
+ "forms": {
+  "documents": {
+    "fields": {
+      "body": {
+        "title": "Body",
+        "description": "The main content of the page",
+        "block": "govspeak"
+      }
+    }
+  }
+ },
+ "presenters": {
+   "publishing_api": {
+    "body": "govspeak"
+  }
+}
"settings": {
-  "edit_screens": {
-   "document": ["body"]
- }

Why

Bunching up properties into 'edit screens' was a good first step in #10786, allowing us to update different block content fields in isolation on separate tabs. But it was too restrictive: we had no way of denoting which fields should be 'grouped' (e.g. start & end date fields for an overall 'duration') and also we were having to wrestle with wanting to present the fields in one way but present them differently when presenting to Publishing API. The previous properties and edit_screens concepts were conflating too much.

The refactoring of the schemas we've done here should make it quicker and easier to iterate document types in future.

Jira: https://gov-uk.atlassian.net/browse/WHIT-2788


⚠️ This repo is Continuously Deployed: make sure you follow the guidance ⚠️

This application is owned by the Whitehall Experience team. Please let us know in #govuk-whitehall-experience-tech when you raise any PRs.

Follow these steps if you are doing a Rails upgrade.

@ChrisBAshton ChrisBAshton force-pushed the configurable-document-form-objects--all-in-one branch 8 times, most recently from d205372 to c41b916 Compare January 6, 2026 16:13
# end
# Is this test needed anymore? We think now that we're using flattened data structures,
# the above tests cover all addition/overwriting/deletion scenarios, and this 'nesting'
# test is now redundant.
Copy link
Contributor Author

@ChrisBAshton ChrisBAshton Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this yesterday - even though we only have flattened top level properties now, we need to make sure that the values are retained, even if the values are nested structures. So make sure we have a test for something like

"foo" => { "bar" => { "baz" => 123 } }

@eYinka eYinka force-pushed the configurable-document-form-objects--all-in-one branch from e640534 to dc80288 Compare January 7, 2026 18:50
@ChrisBAshton ChrisBAshton force-pushed the configurable-document-form-objects--all-in-one branch 2 times, most recently from f22d3d4 to 76a00d5 Compare January 8, 2026 09:19
This now replaces the need for all the `publishing_api_payload` methods defined on all the config driven blocks. There is no need to define a payload behaviour for the `default_object` block, as we always send a flat details hash to publishing API. Only "leaf" blocks will be included in the payload.

We plan to maintain both implementations in the code to de-risk the release. At a later point, we will be removing all the `publishing_api_payload` methods and only use the new flow.

All the tests covering the blocks' `publishing_api_payload` behaviour have been ported over.
@ChrisBAshton ChrisBAshton force-pushed the configurable-document-form-objects--all-in-one branch from 76a00d5 to 25addb1 Compare January 8, 2026 09:26
@eYinka eYinka force-pushed the configurable-document-form-objects--all-in-one branch 2 times, most recently from f83680d to d7218de Compare January 8, 2026 11:30
This commit refactors the schema design for config-driven document types by separating concerns that were previously conflated under edit_screens.

We have:

- Updated the configurable document type schema with new properties such as `presenters` and `forms`.

- Refactored the schema to include `attributes` specifying `type` and `validations`, rather than a hash of properties. This will help us separate the model schema from what we want to render, and send to publishing API, respectively.

- Introduced an alternative configurable block factory builder. It builds uniquely named blocks and abandons the `type > format` nested structure we had in the `blocks` method. Since we now have an easy flat structure of computing the schema/publishing api payload, the `wrapper` object has been dropped in the new method `build_block` as it will be no longer needed.

- Introduced a new way to compute standard edition presenter payload. We want to specify which attributes we're going to be including in the presenter, separately from defining the model attributes, or the forms to render.

- Updated the rendering of standard edition with the new schema format
- Updated the feature tests to support the new schema
- We now "skip" nested objects when rendering; this means that whereas before the form name would have looked like `edition[block_content][wrapper_object][leaf_block]`, it now looks like `edition[block_content][leaf_block]`.
- The way we compose the path when rendering child blocks in the new schema style has also changed.
- Rendering the "required" labels require accessing the `validations`. Validations now live in a different segment of the schema; previously we were fetching them straight from the top-level `schema`; now the "schema" passed for rendering a block only contains `fields` with title/block/description. This was fixed by passing the array of required fields through any `default_object` block, so it's available down the tree. We compute the required fields values in the `ConfigurableDocumentType` model - `required_attributes` method.
- The required attrs are now being passed for the images and the translations edit form. As-is behaviour was missing that too

- Converted all StandardEdition schemas to use new format

Co-authored-by:       Olayinka Oladele <olayinka.oladele@digital.cabinet-office.gov.uk>
Co-authored-by:       Jamie Stamp <jamie.stamp@digital.cabinet-office.gov.uk>
Co-authored-by:       Chris Ashton <christopher.ashton@digital.cabinet-office.gov.uk>
Co-authored-by:       Laura Ghiorghisor <laura.ghiorghisor@digital.cabinet-office.gov.uk>
Co-authored-by:       Ryan Brown <ryan.brown@digital.cabinet-office.gov.uk>
@eYinka eYinka force-pushed the configurable-document-form-objects--all-in-one branch 2 times, most recently from e4b1b4c to 23f85a8 Compare January 8, 2026 17:17
We tried testing setting an object value under the new 'flattened
attributes' structure, and the object was only ever being set as
`{}`. This is because we had special case handling for type "object"
which is no longer necessary - we blindly set the value to the
object, no type casting necessary.

We also no longer have the concept of a nested 'validations'
property on a nested attribute. All validations are declared at
the root level now and can incorporate multiple attributes, as
we're doing with topical event date validation:
https://github.com/alphagov/whitehall/blob/25addb1ce63d150731560b7a99efc89e731ecf21/app/models/configurable_document_types/topical_event.json#L60-L62

Note: There's a failing test in `test/unit/app/models/standard_edition_test.rb:154`. Need to discuss with the team if it's fine to get rid of the test since it looks redundant now.
@eYinka eYinka force-pushed the configurable-document-form-objects--all-in-one branch from 23f85a8 to 56d815a Compare January 8, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants