Ancestry - The tree structure implementations for Elixir Ecto

The tree structure implementations for Elixir Ecto - Ancestry

Inspire by ruby ancestry

Getting started

If available in Hex, the package can be installed
by adding ancestry to your list of dependencies in mix.exs:

def deps do
  [
    {:ancestry, "~> 0.1.2"}
  ]
end

Gen migration file to add string field in your model.

mix ecto.gen.migration add_ancestry_to_<model>

Add ancestry field and index to migration file.

def change do
  alter table(:my_models) do
    add :ancestry, :string
  end
  create index(:my_models, [:ancestry])
end
mix ecto.migration

Add use Ancestry, repo: MyApp.repo to you model.ex

defmodule MyModel do
  use Ecto.Schema
  use Ancestry, repo: MyApp.repo

  import Ecto.Changeset

  schema "my_models" do
    field :ancestry, :string
  end

  def changeset(struct, params) do
    struct
    |> cast(params, [:ancestry])
  end
end

Navigation

method return value usage example finished?
roots all root node MyModel.roots true
parent parent of the record, nil for a root node MyModel.parent(record) true
parent_id parent id of the record, nil for a root node MyModel.parent_id(record) true
has_parent? true if the record has a parent, false otherwise MyModel.has_parent?(record) true
root root of the record’s tree, self for a root node MyModel.root(record) true
root_id root id of the record’s tree, self for a root node MyModel.root_id(record) true
is_root? true if the record is a root node, false otherwise MyModel.is_root?(record) true
ancestors ancestors of the record, starting with the root and ending with the parent MyModel.ancestors(record) true
ancestor_ids ancestor ids of the record MyModel.ancestor_ids(record) true
children direct children of the record MyModel.children(record) true
child_ids direct children’s ids MyModel.child_ids(record) true
has_children? true if the record has any children, false otherwise MyModel.has_children?(record) true
is_childless? true is the record has no children, false otherwise MyModel.is_childless?(record) true
siblings siblings of the record, the record itself is included* MyModel.siblings(record) true
sibling_ids sibling ids MyModel.sibling_ids(record) true
has_siblings? true if the record’s parent has more than one child MyModel.has_siblings?(record) true
is_only_child? true if the record is the only child of its parent MyModel.is_only_child?(record) true
descendants direct and indirect children of the record MyModel.descendants(record) true
descendant_ids direct and indirect children’s ids of the record MyModel.descendant_ids(record) true
subtree the model on descendants and itself MyModel.subtree(record) true
subtree_ids a list of all ids in the record’s subtree MyModel.subtree_ids(record) true
path path of the record, starting with the root and ending with self MyModel.path(record) true
path_ids a list the path ids, starting with the root id and ending with the node’s own id MyModel.path_ids(record) true
depth the depth of the node, root nodes are at depth 0 MyModel.depth(record) true

More pls check it here:

Thank you for reading, have a good day. :slight_smile:

3 Likes

Looks pretty good. For the sake of comparison, there’s also arbor.

Good job. :+1:

2 Likes

The github link is to the wrong library.

Sorry, but now can not edit, right library check here: https://github.com/zven21/ancestry