# `Masu.History`
[🔗](https://github.com/hattoriai/masu/blob/v0.7.0/lib/masu/history.ex#L1)

Where a grid keeps the history of its cells: who changed a cell, when,
from what to what; and a value of the history brought back.

    <.data_grid id="orders" source={Order} repo={Repo} changeset={&Order.changeset/2}
      history={MyApp.GridHistory} user={@user}>

`history` is a module of this behaviour. Masu has two:

  * `Masu.History.Ecto`, a table of any Ecto repo: the grid's own, or
    another database (`use Masu.History.Ecto, repo: MyApp.HistoryRepo`,
    and `mix masu.gen.history` for its migration);
  * `Masu.History.Memory`, in memory, for development and tests.

A store of your own implements the callbacks below over what your app
already keeps (an audit table, PaperTrail, a service).

## What is recorded

Every write of the grid (see `Masu.Write`) that saves: a cell edited,
pasted, filled, undone or restored is an entry of its cell, with its
value before and after, as the browser gets them; a new row and a row
deleted are an entry of the row. The entries of one write (a paste of
200 cells) share a `batch`. Who is the grid's `user` (`:id` and
`:name`); when, the time of the record.

The grid records what its writes save, the grid's own and your
`on_update`'s alike. What your app changes another way (an action's
`Repo.update_all`, a job) it records with `record/2`.

## In the row's transaction, or after it

When the store keeps the history in the grid's own repo (`repo/0`),
the grid's own way of saving (`Masu.Write.save/1`) records a change in
the transaction that saves it: the change and its record are saved
together, or neither. In another repo (a SQLite file next to a
PostgreSQL app, say), no transaction spans both: a change is recorded
just after it is saved, and a node that stops between the two leaves it
unrecorded; a change that was not saved is never recorded. Keep the
history in the main repo when every change must have its record.

An `on_update` of yours that saves in a transaction of its own records
in it with `Masu.Write.record/3`.

# `batch`

```elixir
@callback batch(grid :: String.t(), batch :: String.t()) :: [Masu.History.Entry.t()]
```

The entries of a batch (one write), as recorded.

# `entry`

```elixir
@callback entry(grid :: String.t(), id :: String.t()) :: Masu.History.Entry.t() | nil
```

An entry by its id, or nil.

# `for_cell`

```elixir
@callback for_cell(
  grid :: String.t(),
  row_id :: term(),
  key :: String.t(),
  opts :: keyword()
) :: [
  Masu.History.Entry.t()
]
```

The entries of a cell of the grid, newest first. Options: `:limit`.

# `for_row`

```elixir
@callback for_row(grid :: String.t(), row_id :: term(), opts :: keyword()) :: [
  Masu.History.Entry.t()
]
```

The entries of a row of the grid (of its cells, and of the row), newest first. Options: `:limit`.

# `recent`

```elixir
@callback recent(grid :: String.t(), opts :: keyword()) :: [Masu.History.Entry.t()]
```

The latest entries of the grid, newest first. Options: `:limit`.

# `record`

```elixir
@callback record(entries :: [Masu.History.Entry.t()]) :: :ok
```

Keeps entries.

# `repo`
*optional* 

```elixir
@callback repo() :: module() | nil
```

The Ecto repo that keeps the entries, or nil: when it is the grid's
own, the grid records a change in the transaction that saves it.

# `record`

```elixir
@spec record(module(), [map()]) :: :ok
```

Records entries in `store`: what your app changed another way than the
grid's writes. `fields` of each: `:grid`, `:row_id`, `:key`, `:before`,
`:after` (as the browser gets them), and `:op`, `:origin`, `:batch`,
`:user` (a map of `:id` and `:name`), which the entry takes as they are.

    Masu.History.record(MyApp.GridHistory, [
      %{grid: "orders", row_id: order.id, key: "status", before: "paid", after: "archived",
        origin: :archive, user: user}
    ])

---

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