Reusable cross-world projection calculation.
Replaces typed belongs_to for cross-resource references where the target's
concrete subtype isn't known at the source resource's compile time. The calc
resolves the target to its outermost concrete world at read time via
AshNeo4j.worlds/1 — late-binding by design, open-world by construction.
Used by Diffo.Provider.PlaceRef and Diffo.Provider.PartyRef to replace
their belongs_to relationships pointing at the generic Place/Party/Instance
abstract readers. Also usable directly on consumer leaves that want to point
at any subtype across the cascade (e.g. BaseGeographicSite.address →
GeographicAddress or consumer-domain Address leaf).
Usage
calculate :place, :struct,
{Diffo.Provider.Calculations.ProjectedRef,
[id_field: :place_id, reader: Diffo.Provider.Place]}Options
:id_field(atom, required) — the attribute on the calculated record that holds the target's id.:reader(module, required) — the abstract reader resource for the target type. Lets the calc do a bootstrapAsh.getto load the target node soAshNeo4j.worlds/1can project it to its outermost concrete world. For diffo built-ins:Diffo.Provider.Place,Diffo.Provider.Party,Diffo.Provider.Instance— each kept in core minimally for this role.
Result per input record
nil— the source record'sid_fieldisnil(legitimate absence; no ref to project).- concrete struct — the outermost concrete world's resource, loaded with all subtype-specific attributes.
%Diffo.Unknown{}—id_fieldis set but the target couldn't be projected (see reason vocabulary).
Plus the standard %Ash.NotLoaded{} until the calc is loaded.
Reason vocabulary (local to the calling record's world)
:no_target— bootstrapAsh.getfailed; target id doesn't exist in the graph. Context carries%{id_field: atom, target_id: id, reader: module}.:no_concrete_world— bootstrap loaded butAshNeo4j.worlds/1returned[]. Context carries%{id_field: atom, target_id: id}.:projection_failed— projection identified a concrete world but itsAsh.getfailed. Rare; indicates a Neo4j label / Ash resource mismatch. Context carries%{id_field: atom, target_id: id, resource: module}.
Per the Cross-domain lookups AGENTS.md section, reasons are world-local —
consumers in other worlds should treat them as opaque and (if composing) wrap
via :inner_unknown.
:world stamping
Each %Diffo.Unknown{} is stamped with record.__struct__ — the consumer's
concrete resource (e.g. Diffo.Provider.PlaceRef or MyApp.SomeRef). No
transformer injection needed because the calc runs per-record at runtime and
the consumer's resource is directly available from the record.
Summary
Functions
Callback implementation for Ash.Resource.Calculation.describe/1.
Callback implementation for Ash.Resource.Calculation.has_expression?/0.
Callback implementation for Ash.Resource.Calculation.init/1.
Callback implementation for Ash.Resource.Calculation.strict_loads?/0.
Functions
Callback implementation for Ash.Resource.Calculation.describe/1.
Callback implementation for Ash.Resource.Calculation.has_expression?/0.
Callback implementation for Ash.Resource.Calculation.init/1.
Callback implementation for Ash.Resource.Calculation.strict_loads?/0.