View Source References

Often times, we need to compare values in different fields with each other, not with fixed values. This is where references come in.

Say we want to add a by_owner? predicate to a Todo.Task:

defmodule Todo.Task do
  use Ecto.Schema
  use Dx.Ecto.Schema, repo: Todo.Repo

  schema "tasks" do
    field :completed_at, :utc_datetime

    belongs_to :list, Todo.List
    belongs_to :created_by, Todo.User
  end

  infer by_owner?: true, when: %{created_by_id: {:ref, [:list, :created_by_id]}}
  infer by_owner?: false
end

Operators

By default, all comparisons need to match exactly. However, other comparisons are possible as well.

Say we support completing tasks on an already archived list. And we want to add a predicate completed_later? to capture that.

defmodule Todo.Task do
  use Ecto.Schema
  use Dx.Ecto.Schema, repo: Todo.Repo

  schema "tasks" do
    field :completed_at, :utc_datetime

    belongs_to :list, Todo.List
    belongs_to :created_by, Todo.User
  end

  infer completed_later?: false, when: %{completed?: false}
  infer completed_later?: false, when: %{list: %{archived?: false}}
  infer completed_later?: true, when: %{archived_at: {:gt, {:ref, [:list, :archived_at]}}}
  infer completed_later?: false
end

The Todo.Task must already by completed? and the Todo.List archived?. In particular, the Todo.Task must be completed_at after the Todo.List was archived.

Operators can also compare to fixed values (not references).

Supported operators

Operators with all aliases:

  • Greater than: :gt, :>, :greater_than, :after
  • Greater than or equal: :gte, :>=, :greater_than_or_equal, :on_or_after, :at_or_after
  • Less than: :lt, :<, :less_than, :before
  • Less than or equal: :lte, :<=, :less_than_or_equal, :on_or_before, :at_or_before