How to Create a Basic PubSub Application
From ElixirBlocks
This page is in progress
In LiveView
def mount(_params, _session, socket) do Testbeds.subscribe() {:ok, assign(socket, testbeds: Testbeds.list_testbeds())} end def handle_info({TestBeds, [:testbed | _], _}, socket) do {:noreply, assign(socket, testbeds: TestBeds.list_testbeds())} end
App/test_beds.ex
@topic inspect(__MODULE__) def subscribe do Phoenix.PubSub.subscribe(App.PubSub, @topic) end defp broadcast_change({:ok, result}, event) do Phoenix.PubSub.broadcast(App.PubSub, @topic, {__MODULE__, event, result}) {:ok, result} end # .... def create_testbed(attrs \\ %{}) do %Testbed{} |> Testbed.changeset(attrs) |> Repo.insert() |> broadcast_change([:testbed, :created]) end
Example Without Database
defmodule AppWeb.PageLive do use AppWeb, :live_view def mount(_params, _session, socket) do if connected?(socket) do AppWeb.Endpoint.subscribe(topic) end {:ok, assign(socket, username: username, messages: [])} end def handle_info(%{event: "message", payload: message}, socket) do {:noreply, assign(socket, messages: socket.assigns.messages ++ [message])} end def handle_event("send", %{"text" => text}, socket) do AppWeb.Endpoint.broadcast(topic, "message", %{text: text, name: socket.assigns.username}) {:noreply, socket} end defp username do "User #{:rand.uniform(100)}" end defp topic do "chat" end def render(assigns)do ~H""" <div> <h1>ChatLive</h1> <div class="messages" style="border: 1px solid #eee; height: 400px; overflow: scroll; margin-bottom: 8px;"> <%= for m <- @messages do %> <p style="margin: 2px;"><b><%= m.name %></b>: <%= m.text %></p> <% end %> </div> <form phx-submit="send"> <input type="text" name="text" /> <button type="submit">Send</button> </form> </div> """ end end
# lib/app/counter.ex defmodule Counter do use Agent def start_link(initial_value) do Agent.start_link(fn -> initial_value end, name: __MODULE__) end def value do Agent.get(__MODULE__, & &1) end def increment do Agent.update(__MODULE__, &(&1 + 1)) end end # lib/app_web/live/page_live.ex defmodule AppWeb.PageLive do use AppWeb, :live_view def mount(_params, _session, socket) do Phoenix.PubSub.subscribe(App.PubSub, "the-topic") # Get current value from the supervised Counter data = Counter.value() {:ok, assign(socket, data: data)} end def handle_event("increment", _params, socket) do Counter.increment() new_data = Counter.value() Phoenix.PubSub.broadcast(App.PubSub, "the-topic", new_data) {:noreply, assign(socket, data: new_data)} end def handle_info(new_data_from_broadcast, socket) do # usually set with pattern match like {:data,thedata} IO.inspect new_data_from_broadcast {:noreply, assign(socket, data: new_data_from_broadcast)} end def render(assigns) do ~H""" <div> <.button phx-click="increment">click me </.button> <div>{@data}</div> </div> """ end end