Storehouse.Ecto.Blob (Storehouse v0.2.0)

Copy Markdown View Source

A library of files: a row a file, owned by someone (an account, a site), referenced from many records, kept when the record that first used it is deleted. Its tables are Storehouse.Ecto.Migrations's; which records use each file is Storehouse.Ecto.Usage's.

For a file a record has alone (an avatar, an invoice), a column of the record is simpler: Storehouse.Ecto.File, with no table.

This module is a schema of storehouse_blobs. An app with a table of its own, or fields of its own (a description, a credit), writes its schema with the same fields:

defmodule MyApp.Photo do
  use Storehouse.Ecto.Blob.Schema, usages: "photo_usages"

  schema "photos" do
    Storehouse.Ecto.Blob.Schema.fields()
    field :alt_text, :string
  end
end

and gives it as schema: to this module's functions and Storehouse.Ecto.Usage's. Its migration is Storehouse.Ecto.Migrations.up(blobs: "photos", usages: "photo_usages"), then its own columns.

A file into the library

{:ok, file} = Storehouse.store(upload.path, owner: "sites/7")
{:ok, blob} = Storehouse.Ecto.Blob.insert(Repo, file, owner: "sites/7")

The same file again, for the same owner, is the row the library has: {:existing, blob}, by the checksum.

Summary

Functions

Puts a stored file in the library: {:ok, blob}, or {:existing, blob} when the owner has the same file already (by its checksum), or {:error, changeset}.

Checks that every id of ids is a blob of owner, before a record refers to them: {:ok, ids}, or {:error, {:not_owned, ids}} with those that are not (another's, or none at all). For ids a form or a document sends, which are never to be trusted.

The blob as a Storehouse.File, with its URL in its store: to show it, sign it, make its variants.

In a changeset, the error "is not a file of yours" on field (a list of blob ids) for any id that is not a blob of owner (owned/4).

Types

t()

@type t() :: struct()

Functions

insert(repo, file, opts \\ [])

@spec insert(module(), Storehouse.File.t(), keyword()) ::
  {:ok, t()} | {:existing, t()} | {:error, Ecto.Changeset.t()}

Puts a stored file in the library: {:ok, blob}, or {:existing, blob} when the owner has the same file already (by its checksum), or {:error, changeset}.

Options

  • :owner - whose file it is: the same as Storehouse.store/2's.
  • :store - the store it is kept in, a module. The default is Storehouse.adapter/0.
  • :schema - the blob schema. The default is this module.
  • :attrs - more fields of the app's schema: %{alt_text: "…"}.

owned(repo, ids, owner, opts \\ [])

@spec owned(module(), [String.t()], String.t() | integer() | nil, keyword()) ::
  {:ok, [String.t()]} | {:error, {:not_owned, [String.t()]}}

Checks that every id of ids is a blob of owner, before a record refers to them: {:ok, ids}, or {:error, {:not_owned, ids}} with those that are not (another's, or none at all). For ids a form or a document sends, which are never to be trusted.

Options

  • :schema - the blob schema. The default is this module.

to_file(blob)

@spec to_file(struct()) :: Storehouse.File.t()

The blob as a Storehouse.File, with its URL in its store: to show it, sign it, make its variants.

validate_owned(changeset, field, repo, owner, opts \\ [])

@spec validate_owned(Ecto.Changeset.t(), atom(), module(), term(), keyword()) ::
  Ecto.Changeset.t()

In a changeset, the error "is not a file of yours" on field (a list of blob ids) for any id that is not a blob of owner (owned/4).