The library of saved fragments a host may give Visualize.Chart.Builder (spec/14 §19.7).
The library is the host's: this behaviour is the whole of what the builder knows about
it, so the builder never learns where a fragment is kept or when it is written. A host
with no library gives no store and loses only the library pane.
An entry is where a fragment gets its identity (§19.1, D-99). The store issues each
entry an id — {:style, 11}, {:theme, 32} — from a per-kind sequence it never repeats
(§19.2, D-100), and the entry's name is an attribute nothing references. A fragment's
body carries no name and no id of its own.
The context is whatever the host passes as the second element of a
{module, context} store assign — who is saving, from where — and every callback
receives it. A bare module is {module, nil}.
Example
defmodule MyApp.FragmentStore do
@behaviour Visualize.Chart.Builder.Store
@impl true
def list(_context), do: MyApp.Repo.all(from f in Fragment, select: %{id: ..., name: ...})
@impl true
def get(id, _context), do: ...
@impl true
def put(%{id: nil} = entry, %{user: user}), do: insert(entry, user)
def put(%{id: id} = entry, %{user: user}), do: update(id, entry, user)
@impl true
def delete(id, _context), do: ...
@impl true
def import(bundle, context), do: Visualize.Chart.Builder.Store.relocate(bundle, context, &put/2)
endrelocate/3 is the reference implementation of import/2 over put/2; a store with a
transaction wraps it in one.
This module compiles only when Phoenix.Component is loaded, as every module of the
builder does (spec/10 §1.1, D-45, D-85).
Summary
Types
Whatever the host says about who is saving and from where; nil when it says nothing.
A stored entry. id is nil for one that has not been stored yet; name is the
<group>:<sub-group>:<name> attribute of §18.16; kind is derived from the fragment
(§19.8) and carried so a listing need not load every body.
An entry's identity: its kind and a number the store never repeats (§19.2).
A store as the builder holds it: a module, or a module with its context.
What list/1 returns for each entry: everything but the body.
Callbacks
Removes an entry. A later reference to its id is a mask (§19.2).
The entry stored under an id, or :error when the store no longer holds it.
Imports a bundle: every entry is issued a new id, references inside the bundle are
rewritten through the old => new table, and the whole is committed or nothing is
(§19.7, D-103). References to ids outside the bundle are reported, never a failure.
Every entry, without its body, in the order the library shows them.
Stores an entry. One with no id is new and is issued one; one with an id replaces
what that id holds. {:error, reason} is shown by the builder and not interpreted.
Functions
A string back to an id, or :error. The kind must be one a fragment can have, so no
atom is created from a client's string.
An id as one string, for a data- attribute or an event value.
Imports a bundle through a store's own put/2: the relocation of §19.7.
The module and context of a store assign; a bare module has a nil context.
Types
@type context() :: term()
Whatever the host says about who is saving and from where; nil when it says nothing.
A stored entry. id is nil for one that has not been stored yet; name is the
<group>:<sub-group>:<name> attribute of §18.16; kind is derived from the fragment
(§19.8) and carried so a listing need not load every body.
@type id() :: {atom(), pos_integer()}
An entry's identity: its kind and a number the store never repeats (§19.2).
A store as the builder holds it: a module, or a module with its context.
What list/1 returns for each entry: everything but the body.
Callbacks
Removes an entry. A later reference to its id is a mask (§19.2).
The entry stored under an id, or :error when the store no longer holds it.
@callback import(Visualize.Chart.Builder.Bundle.t(), context()) :: {:ok, %{ids: %{required(id()) => id()}, outside: [id()]}} | {:error, term()}
Imports a bundle: every entry is issued a new id, references inside the bundle are
rewritten through the old => new table, and the whole is committed or nothing is
(§19.7, D-103). References to ids outside the bundle are reported, never a failure.
Every entry, without its body, in the order the library shows them.
Stores an entry. One with no id is new and is issued one; one with an id replaces
what that id holds. {:error, reason} is shown by the builder and not interpreted.
Functions
A string back to an id, or :error. The kind must be one a fragment can have, so no
atom is created from a client's string.
iex> Visualize.Chart.Builder.Store.decode_id("style:11")
{:ok, {:style, 11}}
iex> Visualize.Chart.Builder.Store.decode_id("nonsense:11")
:error
An id as one string, for a data- attribute or an event value.
iex> Visualize.Chart.Builder.Store.encode_id({:style, 11})
"style:11"
@spec relocate(Visualize.Chart.Builder.Bundle.t(), context(), (entry(), context() -> {:ok, id()} | {:error, term()})) :: {:ok, %{ids: %{required(id()) => id()}, outside: [id()]}} | {:error, term()}
Imports a bundle through a store's own put/2: the relocation of §19.7.
Every entry is put with no id, in bundle order, so the store issues a fresh one; the
old => new table is built as it goes; then every entry's fragment is rewritten through
the table and put again under its new id. A reference to an id the bundle does not
carry is left as it is and reported in outside, and resolves as a mask (§19.2).
A store that can wrap this in a transaction should, so the bundle lands whole or not at all; this function itself has no way to undo a put that succeeded.
The module and context of a store assign; a bare module has a nil context.