README.md

# Dagex

Dagex provides tools to create directed, acyclic graphs for your business
entities. It relies on the [PostgreSQL ltree
extension](https://www.postgresql.org/docs/14/ltree.html) and
[Ecto](https://hexdocs.pm/ecto/Ecto.html).

See the module documentation for `Dagex` for usage examples.

## Installation

### 1. Add dependency

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `dagex` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:dagex, "~> 2.0"}
  ]
end
```

### 2. Add Dagex functionality to your Ecto repository:

```elixir
defmodule MyApp.Repo do
  use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres
  use Dagex.Repo
end
```

### 3. Generate a migration to add the necessary database tables and functions

Run `mix ecto.gen.migration add_dagex_to_project` then edit the resulting
migration file:

```elixir
defmodule MyApp.Repo.Migrations.AddDagexToProject do
  use Ecto.Migration
  
  def up do
    Dagex.Migrations.up()
  end
  
  def down do 
    Dagex.Migrations.down()
  end
end
```

and then migrate your database with `mix ecto.migrate`.

### 4. Use migrations to create db tables for the business entities that participate in a DAG:

Run `mix ecto.gen.migration add_organizations` then edit the resulting migration
file:

```elixir
defmodule MyApp.Repo.Migrations.AddOrganizations do 
  require Dagex.Migrations

  use Ecto.Migration 
  
  def change do 
    create table("organizations") do
      add :name, :string, null: false
      timestamps()
    end
    
    # Adds triggers to the "organizations" table to maintain the associated DAG as
    # records are added/removed.
    Dagex.Migrations.setup_node_type("organizations", "2.0.0")
  end
end
```

### 5. Create your Ecto-backed entity and add Dagex functionality:

N.B. You can use any column type that Postgresql can convert to text as the
entity's primary key, however, if your primary key field is a string, you MUST
NOT allow the value `"*"` as this is reserved internally for the supremum of the
graph. You will see an `Ecto.ConstrainError` on the `dagex_reserved_supremum_id`
constraint if you attempt to insert such a record.

```elixir
defmodule MyApp.Organization do 
  use Dagex 
  use Ecto.Schema
  
  schema "organizations" do
    field :name, :string
  end
end
```

See the module documentation for `Dagex` for information on the functionality
that is added to your module when calling `use Dagex`.