Closure Table v0.1.1 CTE.Adapter.Ecto View Source

A CTE Adapter implementation using an existing Ecto Repo for persisting the models.

The current implementation is depending on Ecto ~> 3.1; using Ecto.SubQuery!

For this implementation to work you'll have to provide two tables, and the name of the Repo used by your application:

  1. a table name containing the nodes. Having the id, as a the primary key
  2. a table name where the tree paths will be stores.
  3. the name of the Ecto.Repo, defined by your app

In a future version we will provide you with a convenient migration template to help you starting, but for now you must supply these tables.

For example, given you have the following Schemas for comments:

defmodule CT.Comment do
  use Ecto.Schema
  import Ecto.Changeset

  @timestamps_opts [type: :utc_datetime]

  schema "comments" do
    field :text, :string
    belongs_to :author, CT.Author

    timestamps()
  end
end

and a table used for storing the parent-child relationships

defmodule CT.TreePath do
  use Ecto.Schema
  import Ecto.Changeset
  alias CT.Comment

  @primary_key false

  schema "tree_paths" do
    belongs_to :parent_comment, Comment, foreign_key: :ancestor
    belongs_to :comment, Comment, foreign_key: :descendant
  end
end

we can define the following module:

defmodule CT.MyCTE do
  use CTE,
  otp_app: :cte,
  adapter: CTE.Adapter.Ecto,
  repo: CT.Repo,
  nodes: CT.Comment,
  paths: CT.TreePath
end

We add our CTE Repo to the app's main supervision tree, like this:

defmodule CT.Application do
  use Application

  def start(_type, _args) do
    children = [
      CT.Repo,
      CT.MyCTE
    ]

    opts = [strategy: :one_for_one, name: CT.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

restart out app and then using IEx, we can start experimenting. Examples:

iex» CT.MyCTE.ancestors(9)
{:ok, [1, 4, 6]}

iex» CT.MyCTE.tree(6)
{:ok,
%{
nodes: %{
  6 => %CT.Comment{
    __meta__: #Ecto.Schema.Metadata<:loaded, "comments">,
    author: #Ecto.Association.NotLoaded<association :author is not loaded>,
    author_id: 2,
    id: 6,
    inserted_at: ~U[2019-07-21 01:10:35Z],
    text: "Everything is easier, than with the Nested Sets.",
    updated_at: ~U[2019-07-21 01:10:35Z]
  },
  8 => %CT.Comment{
    __meta__: #Ecto.Schema.Metadata<:loaded, "comments">,
    author: #Ecto.Association.NotLoaded<association :author is not loaded>,
    author_id: 1,
    id: 8,
    inserted_at: ~U[2019-07-21 01:10:35Z],
    text: "I’m sold! And I’ll use its Elixir implementation! <3",
    updated_at: ~U[2019-07-21 01:10:35Z]
  },
  9 => %CT.Comment{
    __meta__: #Ecto.Schema.Metadata<:loaded, "comments">,
    author: #Ecto.Association.NotLoaded<association :author is not loaded>,
    author_id: 3,
    id: 9,
    inserted_at: ~U[2019-07-21 01:10:35Z],
    text: "w⦿‿⦿t!",
    updated_at: ~U[2019-07-21 01:10:35Z]
  }
},
paths: [[6, 6], [6, 8], [6, 9], '       ', '']
}}

Have fun!

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

Initializes the adapter supervision tree by returning the children and adapter metadata.

start the Adapter server

Link to this section Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Initializes the adapter supervision tree by returning the children and adapter metadata.

start the Adapter server