# `Ramal.Preparation`
[🔗](https://github.com/agustinrojas1/ramal/blob/v0.2.0/lib/ramal/preparation.ex#L1)

The read preparation `Ramal.Resource` installs on every read action.

Inside `Ramal.run/2` it makes a read see the base data patched with the branch's overlay. Outside a branch it
returns the query untouched, so the action behaves as if the extension were absent.

How it works, confirmed against Ash 3.37 (`lib/ash/actions/read/read.ex`):

  * `Ash.Query.before_action/2` hooks run after all preparations and before the data-layer query is built, so a hook
    there can still remove `limit` and `offset`. The base query keeps its filter, so Postgres still narrows the rows.
  * `Ash.Query.after_action/2` hooks receive the base rows after the data layer and before relationship loads,
    runtime calculations and the not-found check of `Ash.get/3`. Patching there means loads, calculations and
    `Ash.get/3` all see the patched rows.
  * A relationship load runs a read on the related resource through its own preparation, in a task that does not
    inherit the process dictionary. The branch id therefore also travels in the query's `shared` context, which
    Ash copies into related queries (`lib/ash/actions/read/relationships.ex`).
  * Filters are evaluated on overlay records with `Ash.Filter.Runtime.filter_matches/4` and sorting uses
    Ash.Actions.Sort.runtime_sort/3.

Every base row the read returns is also fingerprinted (`Ramal.Resource.fingerprint/1`) for the staleness check at
merge time, unless the query selected only some attributes.

Known limits in 0.1, documented rather than hidden:

  * aggregates and calculations the data layer computes do not see the overlay; reading one emits
    `[:ramal, :read, :unpatched_aggregate]`. `Ramal.aggregate/4` is the exact alternative for the common kinds;
  * overlay records are added without running the action's `authorize_results` checks, though the query's filter,
    including any policy filter, is applied to them;
  * paginated reads (`page:`) are paged by the database and patched afterwards, so pages can be short or miss rows
    created in the branch, and `count` is the database's.

## Example

    # With a branch current, the same call returns rows created in the branch.
    Ramal.run!(branch, fn -> Ash.read!(MyApp.Farm.Herd) end)

# `init`

# `supports`

# `temporal_safe?`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
