Skip to content

Commit

Permalink
a show and an episode automatically get virtual nodes assigned.
Browse files Browse the repository at this point in the history
these are created when a show and an episode are created
  • Loading branch information
electronicbites committed Dec 8, 2024
1 parent 5c041d9 commit 4584d06
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 18 deletions.
8 changes: 6 additions & 2 deletions lib/radiator/outline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -482,10 +482,14 @@ defmodule Radiator.Outline do

Repo.transaction(fn ->
old_next_node =
NodeRepository.get_node_by_parent_and_prev(get_node_id(parent_node), node.uuid)
NodeRepository.get_node_by_parent_and_prev(
get_node_id(parent_node),
node.uuid,
node.episode_id
)

new_next_node =
NodeRepository.get_node_by_parent_and_prev(new_parent_id, new_prev_id)
NodeRepository.get_node_by_parent_and_prev(new_parent_id, new_prev_id, node.episode_id)

{:ok, node} = NodeRepository.move_node_if(node, new_parent_id, new_prev_id)

Expand Down
37 changes: 33 additions & 4 deletions lib/radiator/outline/node_repository.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,31 @@ defmodule Radiator.Outline.NodeRepository do
|> Repo.insert()
end

@doc """
Creates the internal nodes for a show, this is the global root
and the global inbox.
"""
def create_virtual_nodes_for_show(show_id) do
# create a root node for a show
{:ok, show_root} =
create_node(%{
show_id: show_id,
parent_id: nil,
prev_id: nil,
_type: "global_root"
})

{:ok, global_inbox} =
create_node(%{
show_id: show_id,
parent_id: show_root.uuid,
prev_id: nil,
_type: "global_inbox"
})

{show_root, global_inbox}
end

@doc """
Deletes a node from the repository.
Expand Down Expand Up @@ -150,17 +175,21 @@ defmodule Radiator.Outline.NodeRepository do
end

@doc """
Gets a single node defined by the given prev_id and parent_id.
Gets a single node defined by the given prev_id and parent_id and the
episode id.
TODO: episode id should become a general container id (outline_tree_id)
Returns `nil` if the Node cannot be found.
## Examples
iex> get_node_by_parent_and_prev("5adf3b360fb0", "380d56cf")
iex> get_node_by_parent_and_prev("5adf3b360fb0", "380d56cf", 23)
nil
iex> get_node_by_parent_and_prev("5e3f5a0422a4", "b78a976d")
iex> get_node_by_parent_and_prev("5e3f5a0422a4", "b78a976d", 23)
%Node{uuid: "33b2a1dac9b1", parent_id: "5e3f5a0422a4", prev_id: "b78a976d"}
"""
def get_node_by_parent_and_prev(parent_id, prev_id) do
def get_node_by_parent_and_prev(parent_id, prev_id, episode_id) do
Node
|> where(episode_id: ^episode_id)
|> where_prev_node_equals(prev_id)
|> where_parent_node_equals(parent_id)
|> Repo.one()
Expand Down
36 changes: 30 additions & 6 deletions lib/radiator/podcast.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ defmodule Radiator.Podcast do
"""

import Ecto.Query, warn: false
alias Radiator.Repo

alias Radiator.Outline.NodeRepository
alias Radiator.Podcast.{Episode, Network, Show, ShowHosts}
alias Radiator.Repo

@doc """
Returns the list of networks.
Expand Down Expand Up @@ -182,9 +182,33 @@ defmodule Radiator.Podcast do
"""
def create_show(attrs \\ %{}) do
%Show{}
|> Show.changeset(attrs)
|> Repo.insert()
# also need to create the nodes for the show
# start a transaction =
Repo.transaction(fn ->
result =
%Show{}
|> Show.changeset(attrs)
|> Repo.insert()

case result do
{:ok, show} ->
# create the nodes for the show
{show_root, global_inbox} = NodeRepository.create_virtual_nodes_for_show(show.id)

{:ok, show} =
show
|> Show.changeset_tree(%{
global_root_id: show_root.uuid,
global_inbox_id: global_inbox.uuid
})
|> Repo.update()

show

{:error, changeset} ->
Repo.rollback(changeset)
end
end)
end

@doc """
Expand Down Expand Up @@ -314,7 +338,7 @@ defmodule Radiator.Podcast do
"""
def delete_show(%Show{} = show) do
Repo.delete(show)
Repo.delete(show, allow_stale: true)
end

@doc """
Expand Down
14 changes: 12 additions & 2 deletions lib/radiator/podcast/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ defmodule Radiator.Podcast.Show do
field :description, :string

belongs_to :network, Network

belongs_to :global_root, Node, type: :binary_id, references: :uuid
belongs_to :global_inbox, Node, type: :binary_id, references: :uuid
has_many(:episodes, Episode)
has_many(:outline_nodes, Node)
has_many(:outline_nodes, Node, on_delete: :delete_all)
many_to_many(:hosts, User, join_through: "show_hosts")

timestamps(type: :utc_datetime)
Expand All @@ -28,4 +29,13 @@ defmodule Radiator.Podcast.Show do
|> cast(attrs, [:title, :description, :network_id])
|> validate_required([:title])
end

@doc """
changeset for updating the show's root and inbox nodes
"""
def changeset_tree(show, attrs) do
show
|> cast(attrs, [:global_root_id, :global_inbox_id])
|> validate_required([:global_root_id, :global_inbox_id])
end
end
13 changes: 13 additions & 0 deletions priv/repo/migrations/20241207181658_add_virtual_nodes_to_shows.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule Radiator.Repo.Migrations.AddVirtualNodesToShows do
use Ecto.Migration

def change do
alter table(:shows) do
add :global_root_id,
references(:outline_nodes, on_delete: :delete_all, type: :binary_id, column: :uuid)

add :global_inbox_id,
references(:outline_nodes, on_delete: :delete_all, type: :binary_id, column: :uuid)
end
end
end
11 changes: 7 additions & 4 deletions test/radiator/podcast_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ defmodule Radiator.PodcastTest do

test "list_networks/1 returns all networks with preloaded shows" do
show = show_fixture()
show_id = show.id

assert [%Network{shows: shows}] = Podcast.list_networks(preload: :shows)
assert shows == [show]
assert [%Show{id: ^show_id}] = shows
end

test "get_network!/1 returns the network with given id" do
Expand Down Expand Up @@ -69,12 +70,13 @@ defmodule Radiator.PodcastTest do

test "list_shows/0 returns all shows" do
show = show_fixture()
assert Podcast.list_shows() == [show]
show_id = show.id
assert [%Show{id: ^show_id}] = Podcast.list_shows()
end

test "get_show!/1 returns the show with given id" do
show = show_fixture()
assert Podcast.get_show!(show.id) == show
assert Podcast.get_show!(show.id).id == show.id
end

test "get_show!/2 returns the show with preloaded episodes" do
Expand Down Expand Up @@ -137,8 +139,9 @@ defmodule Radiator.PodcastTest do

test "update_show/2 with invalid data returns error changeset" do
show = show_fixture()
show_id = show.id
assert {:error, %Ecto.Changeset{}} = Podcast.update_show(show, @invalid_attrs)
assert show == Podcast.get_show!(show.id)
assert %Show{id: ^show_id} = Podcast.get_show!(show.id)
end

test "update_show/2 with valid data updates the show by removing hosts" do
Expand Down

0 comments on commit 4584d06

Please sign in to comment.