You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 07f0f49
Browse filesBrowse the repository at this point in the historyBrowse files
feat(objectql): evaluate a formula field over a record in hand the way a read serves it, one hop through a reference included
6
+
7
+
A formula title over lookups (`record.book.title + ' · ' + record.reader.name`) is computed on every read since the formula read path reads one hop. A record no read returned, such as the state a hook fires on, had no way to get the same value: the synchronous `evaluateFormulaField` reads no hop, so it answered `null`.
8
+
9
+
-**`ScopedContext.serveFormulaField(objectName, record, field)`** evaluates one declared formula field over `record` with the read path's own evaluation, under that context: the one hop it reads through a reference (one batched read per reference field, through the reader's own permissions, on the context's transaction when it carries one), the `can()` permission map, and the fault report. A related record the reader may not read, a missing one and a second hop leave the field `null` with the read's reason, as a read does. `ObjectQL.serveFormulaField(objectName, record, field, context)` is the engine method behind it.
10
+
-**`resolveServedRecordTitle(schema, record, channel)`** is the async sibling of `resolveRecordTitle`: this record's title, with a formula title served on `channel` (a `ScopedContext`). `resolveRecordTitle` is unchanged and still reads no hop.
11
+
-**`servedRecordTitle(schema, row)`** reads the title a read already served off the row it returned, instead of re-deriving it.
12
+
13
+
What to do. Nothing. Code that names a record it holds in hand and wants the title a read shows calls `resolveServedRecordTitle` with the caller's `ScopedContext`.
fix(runtime): `ctx.title()` in a hook body answers a title formula that reads through a lookup, as a read of the record shows it
6
+
7
+
A junction object's composed title, `record.book.title + ' · ' + record.reader.name`, is shown by every read of the record, but a hook body's `ctx.title()` answered `null` for it, and `ctx.title('<lookup field>')` answered `null` for a related record whose own title reads through a lookup.
8
+
9
+
-**`ctx.title()`** now reads the one hop the title formula reads, through the body's own `ctx.api` channel: one read per lookup the title reads through, with the caller's permissions, on the transaction the body has open. It follows the lookup's value in this write, so a `beforeInsert` names the payload's book and a `beforeUpdate` that changes `book` names the new book. A title over the record's own columns still costs no read.
10
+
-**`ctx.title('<lookup field>')`** returns the title its `findOne` served, the related record's own one-hop title included, instead of re-computing it without the hop.
11
+
- A related record the caller may not read leaves the title `null`, as the read of the same record shows no title to that caller. It is never a partial title and never the hidden name. A title that would need a second hop is `null`, as it is on a read.
12
+
13
+
What to do. Nothing. A hook that composed a junction object's title by hand can call `ctx.title()` instead.
|`ctx.title()`| This record's title — the object's `nameField`, **including when it is a `formula`** (evaluated server-side against the record already in hand, no extra read). | none |
104
-
|`ctx.title('<lookup field>')`| The related record's title, through a lookup / master_detail / user / tree column. Costs one `findOne`. |`api.read`|
103
+
|`ctx.title()`| This record's title — the object's `nameField`, **including when it is a `formula`** (evaluated server-side against the record already in hand: no extra read over the record's own columns, one read per lookup a title such as `record.book.title + ' · ' + record.reader.name` reads through). | none |
104
+
|`ctx.title('<lookup field>')`| The related record's title, through a lookup / master_detail / user / tree column. Costs one `findOne` (plus the lookups that record's own title reads through). |`api.read`|
|`ctx.connector(name).<method>(...)`_(planned)_| Outbound HTTP / SaaS calls. **Not yet wired into the sandbox** — ships with the separate Connector spec. | (separate Connector spec) |
|`*.title(<argument>)` — the related-record form only; bare `ctx.title()`performs no read|`api.read`|
420
+
|`*.title(<argument>)` — the related-record form only; bare `ctx.title()`names this record and needs no token|`api.read`|
414
421
415
422
The matcher is deliberately over-inclusive — it names spellings the VM does not install (`patch`, `remove`, `get`, `list`, `create`) because an over-inferred token costs nothing the sandbox ever checks, while an under-inferred one surfaces as a sandbox refusal far from its cause. `create` is listed only for that reason: a body spelling it is refused at lowering (see [What the sandbox forbids](#what-the-sandbox-forbids)) and never reaches inference at all.
Copy file name to clipboardExpand all lines: content/docs/ui/react-pages.mdx
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -359,9 +359,9 @@ by tag and through `<Block type="record:…">` alike:
359
359
360
360
```
361
361
✗ Author-time rules failed (1 issue)
362
-
• page "showcase_renewals_pipeline" › <RecordHighlights>: <RecordHighlights> renders "record:highlights", which reads its record from the record context a record page mounts — a kind:'react' page never mounts one, so the block renders empty no matter how it is bound (its objectName/recordId are not read by the renderer).
363
-
fix: On a react page bind the record yourself: <ObjectForm objectName="…" mode="view" recordId={…} fields={[…]} />, or read the record with useAdapter().findOne and lay the strip out in JSX.
364
-
rule: react-block-needs-record-context at pages[27].source
362
+
• page "showcase_renewals_pipeline" › <RecordHighlights>: <RecordHighlights> renders "record:highlights", which reads its record from a record page's context; a kind:'react' page mounts none, so the block renders empty
363
+
fix: Instead: <ObjectForm objectName="…" mode="view" recordId={…} fields={[…]} />, or read the record with useAdapter().findOne and lay the strip out in JSX.
364
+
rule: react-block-needs-record-context at pages[28].source — `os explain react-block-needs-record-context` for why a record block renders empty on a react page
365
365
```
366
366
367
367
The error names the replacement for the block you reached for, so read the hint rather
0 commit comments