What a backend has to do, and what it can promise.
Every impure function in Sheetshow takes a Sheetshow.Workbook and asks
the module named on it to do the work. Three come with the library (Google,
the in-memory one and xlsx), and they are not equals: one evaluates formulas
and resolves an append server-side, another does neither. capabilities/1 is
how that difference is said out loud rather than discovered. Reach for a
backend through Sheetshow.Workbook.google/2, Sheetshow.Workbook.memory/1 or
Sheetshow.Workbook.xlsx/2; the
modules behind them are the library's own business.
iex> Sheetshow.Workbook.memory() |> Sheetshow.Backend.supports?(:evaluates_formulas)
falseThe capabilities:
| capability | what it promises |
|---|---|
:atomic_batch | a plan is applied whole or not at all |
:conditional_write | a write can be refused if the spreadsheet has changed since you read it |
:dimensions | column widths and row heights are kept |
:evaluates_formulas | a formula written here is worked out, so it can be read back as a value |
:server_side_append | an append resolves against the last row at the moment it is applied, so two writers cannot land on each other |
:styles | a cell's style is kept |
:server_side_append is the one Sheetshow.Log rests on, and
:conditional_write is what gives Sheetshow.Table the guarantee Google
cannot; What Sheetshow Can Promise says how.
Summary
Callbacks
Trades credentials for a token. Only a backend that has credentials has this.
What this backend promises for this workbook. Every capability in known/0
has an answer.
Makes the workbook ready to use, and learns its sheets.
Asks the spreadsheet which sheets it has.
The cells in a range. Every range a backend is given names its sheet.
The values in a range, as rows.
The values in several ranges, in the order they were asked for.
Carries out a plan.
Functions
What the workbook's backend promises.
:ok when the backend promises the capability, and an error naming it when
it does not. What a caller uses to refuse before writing rather than after.
Every capability a backend answers for.
Whether the workbook's backend promises one thing.
Types
@type capabilities() :: %{required(capability()) => boolean()}
@type capability() ::
:atomic_batch
| :conditional_write
| :dimensions
| :evaluates_formulas
| :server_side_append
| :styles
Callbacks
@callback authenticate(Sheetshow.Workbook.t()) :: {:ok, Sheetshow.Workbook.t()} | {:error, Sheetshow.Error.t()}
Trades credentials for a token. Only a backend that has credentials has this.
@callback capabilities(Sheetshow.Workbook.t()) :: capabilities()
What this backend promises for this workbook. Every capability in known/0
has an answer.
Per workbook rather than per backend, because a backend's promises can depend
on where it is pointed: the same xlsx codec over a local file cannot refuse a
write that would clobber someone, and over a store that speaks If-Match it
can.
@callback connect(Sheetshow.Workbook.t()) :: {:ok, Sheetshow.Workbook.t()} | {:error, Sheetshow.Error.t()}
Makes the workbook ready to use, and learns its sheets.
@callback fetch_sheets(Sheetshow.Workbook.t()) :: {:ok, Sheetshow.Workbook.t()} | {:error, Sheetshow.Error.t()}
Asks the spreadsheet which sheets it has.
@callback read_cells(Sheetshow.Range.t(), Sheetshow.Workbook.t()) :: {:ok, [Sheetshow.Cell.t()]} | {:error, Sheetshow.Error.t()}
The cells in a range. Every range a backend is given names its sheet.
@callback read_rows(Sheetshow.Range.t(), Sheetshow.Workbook.t()) :: {:ok, [[term()]]} | {:error, Sheetshow.Error.t()}
The values in a range, as rows.
@callback read_rows_batch([Sheetshow.Range.t()], Sheetshow.Workbook.t()) :: {:ok, [[[term()]]]} | {:error, Sheetshow.Error.t()}
The values in several ranges, in the order they were asked for.
@callback run(Sheetshow.Op.plan(), Sheetshow.Workbook.t()) :: {:ok, Sheetshow.Workbook.t()} | {:error, Sheetshow.Error.t()}
Carries out a plan.
Functions
@spec capabilities(Sheetshow.Workbook.t()) :: capabilities()
What the workbook's backend promises.
iex> Sheetshow.Workbook.memory() |> Sheetshow.Backend.capabilities() |> Map.fetch!(:atomic_batch)
true
@spec ensure(Sheetshow.Workbook.t(), capability()) :: :ok | {:error, Sheetshow.Error.t()}
:ok when the backend promises the capability, and an error naming it when
it does not. What a caller uses to refuse before writing rather than after.
iex> {:error, error} = Sheetshow.Workbook.memory() |> Sheetshow.Backend.ensure(:evaluates_formulas)
iex> error.reason
:unsupported
@spec known() :: [capability()]
Every capability a backend answers for.
iex> Sheetshow.Backend.known() |> Enum.member?(:server_side_append)
true
@spec supports?(Sheetshow.Workbook.t(), capability()) :: boolean()
Whether the workbook's backend promises one thing.
iex> Sheetshow.Workbook.memory() |> Sheetshow.Backend.supports?(:server_side_append)
true