diff --git a/.travis.yml b/.travis.yml index 1fa127b..9ae18eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,3 +14,5 @@ cache: directories: - _build - deps +notifications: + email: false diff --git a/README.md b/README.md index f48576e..6828e3b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ defmodule MyApp.AddMaterializedPathToComments do def change do alter table(:comments) do - add :materialized_path, {:array, :integer}, null: false, default: [] + add :path, {:array, :integer}, null: false end end end @@ -253,7 +253,7 @@ You can get depth level of the node in the tree #### `where_depth/2` -You can specify a query to search for nodes with some level of depth +You can specify a query to search for nodes with some level of depth. It uses `CARDINALITY()` postgres function internally, so ensure your postgres version is at least `9.4`. ``` elixir Comment.where_depth(Comment, is_bigger_than: 2) # => Find all nodes with more than 2 levels deep @@ -323,3 +323,15 @@ Comment.brutalist_root(comment) Comment.brutalist_root?(comment) # et.c. ``` + +## About [Brutalist](https://brutalist.press) + + + Brutalist + +

+ +`ecto_materialized_path` package is maintained and funded by folks from [Brutalist](https://brutalist.press) - media platform for writing and sharing news and stories with strong focus on traditional values, think-tank level analytics and political research. diff --git a/brutalist_logo.png b/brutalist_logo.png new file mode 100644 index 0000000..e198f5a Binary files /dev/null and b/brutalist_logo.png differ diff --git a/lib/ecto_materialized_path.ex b/lib/ecto_materialized_path.ex index a809e87..ca3eea9 100644 --- a/lib/ecto_materialized_path.ex +++ b/lib/ecto_materialized_path.ex @@ -130,19 +130,19 @@ defmodule EctoMaterializedPath do end defp do_where_depth(query, [is_bigger_than: ibt], column_name) when is_integer(ibt) and ibt > 0 do - Ecto.Query.from(q in query, where: fragment("array_length(?, 1)", ^column_name) > ^ibt) + Ecto.Query.from(q in query, where: fragment("CARDINALITY(?) > ?", field(q, ^column_name), ^ibt)) end defp do_where_depth(query, [is_bigger_than_or_equal_to: ibtoet], column_name) when is_integer(ibtoet) and ibtoet >= 0 do - Ecto.Query.from(q in query, where: fragment("array_length(?, 1)", ^column_name) >= ^ibtoet) + Ecto.Query.from(q in query, where: fragment("CARDINALITY(?) >= ?", field(q, ^column_name), ^ibtoet)) end defp do_where_depth(query, [is_equal_to: iet], column_name) when is_integer(iet) and iet > 0 do - Ecto.Query.from(q in query, where: fragment("array_length(?, 1)", ^column_name) == ^iet) + Ecto.Query.from(q in query, where: fragment("CARDINALITY(?) = ?", field(q, ^column_name), ^iet)) end defp do_where_depth(query, [is_smaller_than_or_equal_to: istoet], column_name) when is_integer(istoet) and istoet >= 0 do - Ecto.Query.from(q in query, where: fragment("array_length(?, 1)", ^column_name) <= ^istoet) + Ecto.Query.from(q in query, where: fragment("CARDINALITY(?) <= ?", field(q, ^column_name), ^istoet)) end defp do_where_depth(query, [is_smaller_than: ist], column_name) when is_integer(ist) and ist > 0 do - Ecto.Query.from(q in query, where: fragment("array_length(?, 1)", ^column_name) < ^ist) + Ecto.Query.from(q in query, where: fragment("CARDINALITY(?) < ?", field(q, ^column_name), ^ist)) end defp do_where_depth(_, _, _) do raise ArgumentError, "invalid arguments" @@ -160,6 +160,7 @@ defmodule EctoMaterializedPath do changeset |> Ecto.Changeset.change(%{ :"#{column_name}" => new_path }) end + def arrange([], _), do: [] def arrange(nodes_list, column_name) do nodes_depth_map = nodes_list |> nodes_by_depth_map(%{}, column_name) diff --git a/lib/ecto_materialized_path/path.ex b/lib/ecto_materialized_path/path.ex index d9d5959..f316f39 100644 --- a/lib/ecto_materialized_path/path.ex +++ b/lib/ecto_materialized_path/path.ex @@ -7,7 +7,7 @@ defmodule EctoMaterializedPath.Path do """ def cast(list) when is_list(list) do - path_is_correct? = Enum.all?(list, fn(path_id) -> is_integer(path_id) end) + path_is_correct? = Enum.all?(list, fn(path_id) -> (is_integer(path_id) || is_binary(path_id)) end) if path_is_correct? do { :ok, list } diff --git a/mix.exs b/mix.exs index 202d36f..303065c 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule EctoMaterializedPath.Mixfile do use Mix.Project @project_url "https://github.com/asiniy/ecto_materialized_path" - @version "0.1.0" + @version "0.2.0" def project do [ diff --git a/test/ecto_materialized_path/path_test.exs b/test/ecto_materialized_path/path_test.exs index e9616b5..8ddba79 100644 --- a/test/ecto_materialized_path/path_test.exs +++ b/test/ecto_materialized_path/path_test.exs @@ -11,11 +11,15 @@ defmodule EctoMaterializedPath.PathTest do assert Path.cast([13, 45, 18]) == { :ok, [13, 45, 18] } end + test "passes with UUID's" do + assert Path.cast(["38432046-4351-4676-8988-10f0262da113", "a65ce828-52f2-4931-8719-9f7d97723f3b"]) == { :ok, ["38432046-4351-4676-8988-10f0262da113", "a65ce828-52f2-4931-8719-9f7d97723f3b"] } + end + test "fails with random value" do assert Path.cast(4) == :error end test "fails with wrongs path" do - assert Path.cast([14, "ee", 45]) == :error + assert Path.cast([14, [:ok], 45]) == :error end end diff --git a/test/ecto_materialized_path_test.exs b/test/ecto_materialized_path_test.exs index 8e29191..27baff0 100644 --- a/test/ecto_materialized_path_test.exs +++ b/test/ecto_materialized_path_test.exs @@ -367,7 +367,11 @@ defmodule EctoMaterializedPathTest do ] end - test "raises an exception when node isn't arranged" do + test "returns empty list if there are no children" do + assert Comment.arrange([]) == [] + end + + test "raises an exception when node can't arranged" do comment_1 = %Comment{ id: 1 } comment_3 = %Comment{ id: 3, path: [1] } # parent is missing