# `Chronicle.ReadModel`
[🔗](https://github.com/Cratis/Chronicle.Elixir/blob/main/lib/chronicle/read_model.ex#L4)

Macro for defining Chronicle read models with embedded model-bound projections.

Use `Chronicle.ReadModel` in a struct module to define both the read model
shape and how Chronicle should project events into it. The projection
definition lives right next to the struct fields — no separate projection
module is needed.

## Quick Example

    defmodule MyApp.ReadModels.Account do
      use Chronicle.ReadModel

      defstruct account_id: nil, owner_name: nil, balance: 0, transaction_count: 0

      from MyApp.Events.AccountOpened,
        key: "$eventSourceId",
        set: [
          account_id: "$eventSourceId",
          owner_name: "OwnerName",
          balance: "InitialBalance"
        ]

      from MyApp.Events.FundsDeposited,
        key: "$eventSourceId",
        add: [balance: "Amount", transaction_count: 1]

      from MyApp.Events.FundsWithdrawn,
        key: "$eventSourceId",
        subtract: [balance: "Amount"],
        add: [transaction_count: 1]
    end

## Projection Macros

### `from/2`

Maps properties from an event onto the read model.

    from MyApp.Events.AccountOpened,
      key: "$eventSourceId",
      set: [account_id: "$eventSourceId", owner_name: "OwnerName"],
      count: :transaction_count

Options:
  * `:key` — key expression identifying the model instance (default: `"$eventSourceId"`)
  * `:parent_key` — parent key for nested models
  * `:set` — keyword list of `field: expression` pairs to set directly
  * `:add` — keyword list of `field: expression` pairs to add to
  * `:subtract` — keyword list of `field: expression` pairs to subtract from
  * `:count` — field atom to increment by 1 on each event occurrence

### `join/2`

Joins a secondary event onto the model by a matching field.

    join MyApp.Events.AccountVerified,
      on: "AccountId",
      key: "$eventSourceId",
      set: [verified: true]

Options:
  * `:on` — **(required)** the field name in the event to join on
  * `:key` — key expression (default: `"$eventSourceId"`)
  * `:set`, `:add`, `:subtract` — property mappings

### `removed_with/2`

Removes the model instance when the given event occurs.

    removed_with MyApp.Events.AccountClosed,
      key: "$eventSourceId"

Options:
  * `:key` — key expression (default: `"$eventSourceId"`)
  * `:parent_key` — parent key for nested models

### `from_every/1`

Applies property mappings on every event, regardless of type.

    from_every set: [last_activity: "Occurred"]

Options:
  * `:set`, `:add`, `:subtract` — property mappings applied to every event

## Property Expressions

Values in `set:`, `add:`, and `subtract:` lists are Chronicle property path
expressions:

| Expression | Meaning |
|-----------|---------|
| `"OwnerName"` | The `OwnerName` field from the event |
| `"$eventSourceId"` | The event source identifier |
| `"$occurred"` | When the event was recorded |
| `1` | A literal integer constant |
| `"Amount"` | A named field from the event payload |

## Registering with Chronicle.Client

    {Chronicle.Client,
      ...
      read_models: [MyApp.ReadModels.Account]}

## Introspection

    MyApp.ReadModels.Account.__chronicle_read_model__(:id)
    MyApp.ReadModels.Account.__chronicle_read_model__(:from)
    MyApp.ReadModels.Account.__chronicle_read_model__(:join)
    MyApp.ReadModels.Account.__chronicle_read_model__(:removed_with)
    MyApp.ReadModels.Account.__chronicle_read_model__(:from_every)
    MyApp.ReadModels.Account.__chronicle_read_model__(:has_projection?)

# `from`
*macro* 

Declares how an event maps onto this read model.

See the `Chronicle.ReadModel` module documentation for full options.

# `from_every`
*macro* 

Applies property mappings on every event, regardless of type.

See the `Chronicle.ReadModel` module documentation for full options.

# `join`
*macro* 

Declares a join from a secondary event onto this read model.

See the `Chronicle.ReadModel` module documentation for full options.

# `removed_with`
*macro* 

Declares that this model is removed when the given event occurs.

See the `Chronicle.ReadModel` module documentation for full options.

---

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