Expression.Context (expression v3.0.0-rc.0)

Copy Markdown

A helper module for creating a context that can be used with Expression.Eval.

Plain map context

new/2 returns a plain map. By default it preserves original key casing (variable lookup is case-insensitive at evaluation time) and leaves string values untouched. Atom keys are stringified.

iex> Expression.Context.new(%{foo: "bar"}) %{"foo" => "bar"} iex> Expression.Context.new(%{FOO: "bar"}) %{"FOO" => "bar"} iex> Expression.Context.new(%{foo: %{bar: "baz"}}) %{"foo" => %{"bar" => "baz"}} iex> Expression.Context.new(%{Foo: %{Bar: "baz"}}) %{"Foo" => %{"Bar" => "baz"}} iex> Expression.Context.new(%{foo: %{bar: 1}}) %{"foo" => %{"bar" => 1}} iex> Expression.Context.new(%{date: "2020-12-13T23:34:45"}) %{"date" => "2020-12-13T23:34:45"} iex> Expression.Context.new(%{boolean: "true"}) %{"boolean" => "true"} iex> Expression.Context.new(%{float: 1.234}) %{"float" => 1.234}

Pass lowercase_keys: true and/or coerce_strings: true to opt in to v2-style normalization:

iex> Expression.Context.new(%{FOO: "bar"}, lowercase_keys: true) %{"foo" => "bar"} iex> Expression.Context.new(%{date: "2020-12-13T23:34:45"}, coerce_strings: true) %{"date" => ~U[2020-12-13 23:34:45.0Z]} iex> Expression.Context.new(%{boolean: "true"}, coerce_strings: true) %{"boolean" => true} iex> Expression.Context.new(%{mixed: ["2020-12-13T23:34:45", 1, "true", "binary"]}, coerce_strings: true) %{"mixed" => [~U[2020-12-13 23:34:45.0Z], 1, true, "binary"]}

Options

new/2 accepts the following options:

  • :lowercase_keys - when true, all keys are lowercased. Default is false. Variable lookup remains case-insensitive at evaluation time regardless of this setting.
  • :coerce_strings - when true, string values are auto-parsed to their typed equivalents (dates, booleans, numbers). Default is false.

Structured context with private state

build/2 returns an %Expression.Context{} struct that separates user-visible variables from callback-private state.

Variable resolution (@foo) only reads from vars. Callbacks receive the full struct and can access private for trusted data (database records, tokens, internal IDs) that expression authors must not be able to read.

iex> ctx = Expression.Context.build(%{name: "Jane"}, private: %{number: %{uuid: "abc"}}) iex> ctx.vars["name"] "Jane" iex> ctx.private %{number: %{uuid: "abc"}}

Summary

Functions

Build a structured context with separate variable and private state compartments.

Types

t()

@type t() :: %Expression.Context{private: map(), vars: map()}

Functions

build(vars, opts \\ [])

@spec build(map(), Keyword.t()) :: t()

Build a structured context with separate variable and private state compartments.

Variable resolution (@foo) only reads from vars. Callbacks receive the full struct and can access private for trusted data that expression authors must not be able to read.

Options

  • :private - a map of callback-only data (default: %{})

Any other options are passed through to new/2 for variable normalization.

Examples

iex> ctx = Expression.Context.build(%{name: "Jane"}, private: %{token: "secret"})
iex> ctx.vars["name"]
"Jane"
iex> ctx.private.token
"secret"

new(ctx, opts \\ [])

@spec new(map(), Keyword.t() | nil) :: map()