View Source Alembic.Loader (alembic v0.1.0)
Resolves template names to files across one or more configured template root directories and reads their contents. Supports multiple roots (checked in order, first match wins), automatic extension appending when a template name has none, and path-traversal protection.
File.read/1 (and File.stat/2) are called directly on each candidate
path — never File.exists?/1 first. Checking existence and then reading
is a TOCTOU race; attempting the read/stat and handling its error is the
correct approach.
Summary
Functions
Builds a (name -> {:ok, source} | {:error, reason}) function capturing
opts — used for dependency injection into
Alembic.Inheritance.resolve_chain/3.
Reads a template's content by name, walking opts[:roots] (or
config :alembic, :template_roots) in order.
Resolves name to an absolute path across the configured roots, without
reading its content. Added beyond issue 1.5.1's own public API: the
top-level pipeline (Alembic.render_file/3, issue 1.5.3) needs the fully
resolved path — not just its content — to use as Alembic.Cache's cache
key, since the cache is keyed by a real, statable filesystem path, not a
root-relative template name.
Returns the mtime of a resolved template — used by Alembic.Cache to
detect a stale entry.
Types
Functions
Builds a (name -> {:ok, source} | {:error, reason}) function capturing
opts — used for dependency injection into
Alembic.Inheritance.resolve_chain/3.
Examples
iex> loader = Alembic.Loader.build_loader(roots: ["test/fixtures/templates"])
iex> {:ok, content} = loader.("base.html")
iex> content =~ "Alembic"
true
Reads a template's content by name, walking opts[:roots] (or
config :alembic, :template_roots) in order.
Examples
iex> {:ok, content} = Alembic.Loader.load("base.html", roots: ["test/fixtures/templates"])
iex> content =~ "Alembic"
true
iex> {:error, {:template_not_found, paths}} = Alembic.Loader.load("nope.html", roots: ["test/fixtures/templates"])
iex> Enum.any?(paths, &String.ends_with?(&1, "nope.html"))
true
Resolves name to an absolute path across the configured roots, without
reading its content. Added beyond issue 1.5.1's own public API: the
top-level pipeline (Alembic.render_file/3, issue 1.5.3) needs the fully
resolved path — not just its content — to use as Alembic.Cache's cache
key, since the cache is keyed by a real, statable filesystem path, not a
root-relative template name.
Examples
iex> {:ok, path} = Alembic.Loader.resolve_path("base.html", roots: ["test/fixtures/templates"])
iex> Path.type(path)
:absolute
@spec stat( String.t(), keyword() ) :: {:ok, DateTime.t()} | {:error, reason() | File.posix()}
Returns the mtime of a resolved template — used by Alembic.Cache to
detect a stale entry.
Examples
iex> {:ok, mtime} = Alembic.Loader.stat("base.html", roots: ["test/fixtures/templates"])
iex> match?(%DateTime{}, mtime)
true