We plan to evaluate Uni Ecto Plugin against three criteria:
| Criterion | Vanilla Ecto | Uni Plugin | Notes |
|-----------|--------------|------------|-------|
| Lines of code for 4 plugins (soft-delete, encrypt, audit, tenant) | ~240 LOC | ~60 LOC | Across 5 schemas |
| Plugin conflict resolution | Manual | Ordered priority | User defines order |
| Query composition (e.g., soft-delete + tenant) | Manual where | Automatic via plugin chain | modify_query composes |
| Runtime overhead | 0 | <5% | Macro-expanded per plugin |
defmodule MyApp.Task do use Ecto.Schema use UniEctoPlugin.SoftDelete use UniEctoPlugin.Audit uni ecto plugin
schema "tasks" do field :title, :string timestamps() end end
lib/uni_ecto_plugin/tenancy.ex
defmodule UniEctoPlugin.Tenancy do defmacro __using__(opts) do tenant_field = Keyword.get(opts, :tenant_field, :tenant_id)quote do import Ecto.Query @tenant_field unquote(tenant_field) field @tenant_field, :integer def scope_tenant(query, tenant_id) do from q in query, where: field(q, ^@tenant_field) == ^tenant_id end def set_tenant(changeset, tenant_id) do Ecto.Changeset.put_change(changeset, @tenant_field, tenant_id) end def before_insert(changeset, tenant_id) do set_tenant(changeset, tenant_id) end end
end end
Usage:
defmodule MyApp.Blog.Comment do use Ecto.Schema use UniEctoPlugin.Tenancy, tenant_field: :account_id
schema "comments" do field :content, :string timestamps() end endWe plan to evaluate Uni Ecto Plugin against