Skip to content

Keep an import warning's file apart from its message, and settle the wording - #61

Draft
njakobsen wants to merge 1 commit into
masterfrom
spatial-notice-layout
Draft

Keep an import warning's file apart from its message, and settle the wording#61
njakobsen wants to merge 1 commit into
masterfrom
spatial-notice-layout

Conversation

@njakobsen

@njakobsen njakobsen commented Aug 8, 2026

Copy link
Copy Markdown
Member

The file and the message were welded together

A warning was stored as one pre-joined string:

"TLH_Heliskiing_Tenure_Shapefiles.zip/tlh_ski_zone_areas_bc_albers_nov_29_2021_pl.shp: This shapefile is incomplete — ..."

The host app had nothing to lay out but a sentence. Uploads routinely carry several files that fail the same way, so the reader got the same explanation repeated once per file. #feature_update_warnings now returns {'file' => ..., 'message' => ...} pairs, so a caller can show the explanation once and list the files it covers.

Warnings stored before this are plain strings. They come back whole as the message and render as written, rather than being guessed apart on a colon a filename may contain.

Warnings survive a failed import

store_feature_update_warnings ran inside the transaction that the EmptyImportError rolls back, so a failed import could only ever explain itself through the exception message — one unbroken paragraph, and gone as soon as the job was cleared. They are now written again after the rollback.

One rule for the wording

The messages followed no single shape. Two led with an em dash before naming the missing part; one spliced three clauses together before its first full stop; two stopped after describing the problem without saying what to do.

  • An error states what is wrong with the file.
  • A warning states what was skipped, and why it could not be imported.

Neither tells the reader what to do about it. The gem is handed a file and cannot know whether it was uploaded, fetched from a URL or configured by an administrator, so it cannot know what action is open to whoever reads the message — "upload it again" is a guess. A host knows its own workflow and is the place to add one.

The file is the subject of every message, never the reader and never the library. A gem has no voice to speak in and cannot know who is reading, so first and second person are gone.

Before After
This shapefile is incomplete — X.shx is missing. A shapefile is a set of files that have to be zipped up together: .shp, .shx, .dbf and .prj. This shapefile is missing X.shx. A shapefile is made up of .shp, .shx, .dbf and .prj files.
This shapefile has no projection file — X.prj is missing, so there is no way to tell where on the earth it belongs. Re-export… This shapefile has no projection file (X.prj), so its place on the earth is unknown.
This archive has no shapefile (.shp) in it. …same, plus Supported formats are KMZ, KML, …
This file couldn't be opened. It may be damaged, or saved in a format we can't read. This file could not be opened. It may be damaged or in an unsupported format.
Invalid KML document (root node was 'Folder') This KML file could not be read: its root element is 'Folder', not 'kml'.
layer.kmz isn't a file type we can read. Please upload a KMZ, KML, … This file type is not supported. Supported formats are KMZ, KML, …
One or more features you are trying to import has text encoded in an un-supported format (…) This file contains text in an unsupported character encoding (…). Text must be encoded as UTF-8.
Skipped 1 network-linked layer: BEC Map. Network links point at data stored somewhere else rather than holding it, so there is nothing to import from them. Skipped 1 network-linked layer (BEC Map). A network link points at data held on another server rather than containing it, so there is nothing to import.

Both em dashes are gone; what they introduced now sits in the first sentence or in parentheses, which is also how a skipped layer's name reads. The invalid-KML message stops being developer-facing: root node was 'Folder' told a submitter nothing they could act on.

Breaking

  • #feature_update_warnings returns hashes, not strings.
  • INVALID_ARCHIVE changes from "This file doesn't contain any map data." to "This file contains no map data.".
  • SUPPORTED_FORMATS changes from "Please upload a KMZ, ..." to "Supported formats are KMZ, ...".

The README gains an Upgrading From 3.11 to 3.12 section covering all three, the way every earlier breaking change in this gem has been documented.

Version goes to 3.12.0 rather than a patch for the return-type change. ~> 3.11 still accepts it, so a host that lays the file and message out separately should tighten its constraint to ~> 3.12.

Testing

Full suite: 269 examples, 0 failures. Four assertions moved with the wording, and the warning specs now pin file and message separately, which is the new contract.

Verified against real uploads rather than fixtures: re-importing one record's seven files produced 674 features and two warnings naming the two .shp files missing their .shx — the same recovery measured before this change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HLgkg1oN6dkKfLzhKyDUFt

@njakobsen
njakobsen force-pushed the spatial-notice-layout branch 2 times, most recently from 19d2d90 to 89fe1d8 Compare August 10, 2026 09:46
…e the wording

A warning was stored as one pre-joined string, `"upload.zip: This file contains no map data."`, and the host app had nothing to lay out but a sentence. Several files in one upload routinely fail the same way, so a reader got the same explanation repeated once per file, joined into a paragraph by `to_sentence`. Storing the pair instead lets a caller show the explanation once and list the files it covers.

Warnings are now also kept when an import fails. The transaction that recorded them rolls back with the `EmptyImportError`, so a failed import could previously only explain itself through the exception message — one unbroken paragraph, gone as soon as the job was cleared.

The messages themselves followed no single shape: two led with an em dash before naming the missing part, one spliced three clauses together before its first full stop, and one was written for a developer. They now follow one rule. Each says what is wrong with the file, and where it helps, what a valid file holds instead. None tells the reader what to do about it: the gem is handed a file and cannot know whether it was uploaded, fetched from a URL or configured by an administrator, so it cannot know what action is open to whoever reads the message. A host knows its own workflow and is the place to add one. Specifics that an em dash used to introduce sit in the first sentence or in parentheses, which is also how a skipped layer's name now reads.

The file is the subject of every message, never the reader and never the library. A gem has no voice to speak in and cannot know who is reading, so `"This isn't a file type we can read."` becomes `"This file type is not supported."` and `"Please upload a KMZ..."` becomes `"Supported formats are KMZ..."`.

The encoding error, which disagreed with itself grammatically (`One or more features ... has`) and spelled unsupported with a hyphen, now names the encoding a file needs instead. `Invalid KML document (root node was 'Folder')` was developer-facing — it now names the root element in a sentence a submitter can read.

`INVALID_ARCHIVE` changes from "This file doesn't contain any map data." to "This file contains no map data.", and `SUPPORTED_FORMATS` from "Please upload a KMZ, ..." to "Upload a KMZ, ...", so a caller matching on either text needs updating.

The README gains an `Upgrading From 3.11 to 3.12` section, the way every earlier breaking change in this gem has been documented. It covers the return type, the pre-joined strings a caller will still meet in records stored before the upgrade, and the one-liner that rebuilds the 3.11 sentence for a caller that wants to keep rendering one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@njakobsen
njakobsen force-pushed the spatial-notice-layout branch from 89fe1d8 to 9563c25 Compare August 10, 2026 10:48
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.

1 participant