fbutano
List of nested maps not working from liveview
Hello, I have a small phoenix app with just one ecto model called Office with the following schema for parent relationship
defmodule Tree.Arma.Office do
use Ecto.Schema
import Ecto.Changeset
schema "offices" do
field :name, :string
belongs_to :parent, Tree.Arma.Office
has_many :children, Tree.Arma.Office
timestamps(type: :utc_datetime)
end
@doc false
def changeset(office, attrs) do
office
|> cast(attrs, [:id, :name, :parent_id])
|> validate_required([:name])
end
end
Inside Arma context I have the following helper function to retrieve a linear list of offices in parent-children relations and works perfectly
def list_descendants(id) do
base_query =
Office
|> where(id: ^id)
recursive_query =
Office
|> join(:inner, [next_descendant], parent in "descendants_list",
on: next_descendant.parent_id == parent.id
)
descendants_query = base_query |> union_all(^recursive_query)
{"descendants_list", Office}
|> recursive_ctes(true)
|> with_cte("descendants_list", as: ^descendants_query)
|> where([o], o.id != ^id)
|> Repo.all()
end
I have also defined the following functions to retrieve a nested map of descendants:
def nested_tree(parent_id) do
flat_list = list_descendants(parent_id)
nester(flat_list, parent_id)
end
def nester(flat_list, root_id) do
lookup = Enum.group_by(flat_list, & &1.parent_id)
with_children(root_id, lookup)
end
defp with_children(root_id, lookup) do
lookup
|> Map.get(root_id, [])
|> Enum.map(&nest_one(&1, lookup))
end
defp nest_one(row, lookup) do
%{row | children: with_children(row.id, lookup)}
end
So, if we have an Office with id=4 and call nested_tree(4) the function returns a nested map of all the descendants from the Office with id=4.
The problem is that when i call nested_tree from inside an iex -S mix shell all works fine; but when i the function is called from the liveview that shows the details for a sibgle Office, nested_tree() return an empty list. This is the code of the liveview:
defmodule TreeWeb.OfficeLive.Show do
use TreeWeb, :live_view
alias Tree.Arma
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:office, Arma.get_office!(id))
|> assign(:office_tree, Arma.nested_tree(id))
}
end
defp page_title(:show), do: "Show Office"
defp page_title(:edit), do: "Edit Office"
end
I’ve found that if in the liveview the id of the office is hardcoded when calling nested_tree() it works!
So for example if in the liveview I put:
|> assign(:office_tree, Arma.nested_tree(4)
it works!
I’m really stuck with this, so if anybody can help me I really appreciate!!
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #performance
- #security










Marked As Solved
nTraum
Then maybe passing the ID either as a string or as an integer is the reason for the different behaviour you observe.
The
paramsmap in thehandle_paramsfunction always contains string values as far as I know. What happens if you parse to an integer before passing it to your functions?Last Post!
fbutano
It works! perfect explanation and solution to the problem!
Many thanks for your fast reply!