I’m playing a game where I intentionally create errors in my programs to see if I can fix them based on console output alone.
Cliff notes answer: I can’t
In JS I feel like errors are more direct and I can fix a program by finding the file and line number, and working backwards.
In Elixir I wouldn’t be able to fix a codebase that is handed to me from another developer without the help of forums and Google.
So for example, this error below is the result of me changing a function argument.
I went from this:
def handle_event("send", %{"text" => text}, socket) do # This is what I changed below
IO.inspect text
Phoenix.PubSub.broadcast(App.PubSub, topic, {:text_stuff, text})
{:noreply, socket}
end
To this
def handle_event("send", text, socket) do # This is what I changed
IO.inspect text
Phoenix.PubSub.broadcast(App.PubSub, topic, {:text_stuff, text})
{:noreply, socket}
end
The code is part of a larger Live View (below)
I would like to know how to use the errors to work backwards fix this. If anyone wants to share their thought process I would like to read it.
Error
`[error] GenServer #PID<0.1420.0> terminating
** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for %{"text" => "ad"} of type Map. This protocol is implemented for the following type(s): Atom, BitString, Date, DateTime, Decimal, Float, Integer, List, NaiveDateTime, Phoenix.HTML.Form, Phoenix.LiveComponent.CID, Phoenix.LiveView.Component, Phoenix.LiveView.Comprehension, Phoenix.LiveView.JS, Phoenix.LiveView.Rendered, Time, Tuple, URI
(phoenix_html 3.3.2) lib/phoenix_html/safe.ex:1: Phoenix.HTML.Safe.impl_for!/1
(phoenix_html 3.3.2) lib/phoenix_html/safe.ex:15: Phoenix.HTML.Safe.to_iodata/1
(app 0.1.0) lib/app_web/live/send_live.ex:38: anonymous fn/2 in AppWeb.SendLive.render/1
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:375: Phoenix.LiveView.Diff.traverse/7
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:544: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
(elixir 1.14.3) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:373: Phoenix.LiveView.Diff.traverse/7
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:139: Phoenix.LiveView.Diff.render/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:833: Phoenix.LiveView.Channel.render_diff/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:689: Phoenix.LiveView.Channel.handle_changed/4
(stdlib 4.2) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.2) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: {:text_stuff, %{"text" => "ad"}}
State: %{components: {%{}, %{}, 1}, join_ref: "4", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<id: "phx-F3-xORYdOS-9swdH", endpoint: AppWeb.Endpoint, view: AppWeb.SendLive, parent_pid: nil, root_pid: #PID<0.1420.0>, router: AppWeb.Router, assigns: %{__changed__: %{}, flash: %{}, live_action: :home, message_item: ""}, transport_pid: #PID<0.1413.0>, ...>, topic: "lv:phx-F3-xORYdOS-9swdH", upload_names: %{}, upload_pids: %{}}`
Full LIve VIew Page
defmodule AppWeb.SendLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
if connected?(socket) do
Phoenix.PubSub.subscribe(App.PubSub, topic)
end
{:ok, assign(socket, message_item: "")}
end
def handle_info({:text_stuff, text}, socket) do
{:noreply, assign(socket, message_item: text)}
end
def handle_event("send", %{"text" => text}, socket) do # This is what I changed
IO.inspect text
Phoenix.PubSub.broadcast(App.PubSub, topic, {:text_stuff, text})
{:noreply, socket}
end
defp topic do #Topic
"message"
end
def render(assigns)do
~H"""
<div>
<h1>Send Message</h1>
<form phx-submit="send">
<input type="text" name="text" />
<button type="submit">Send</button>
</form>
<div>
<h1>ChatLive</h1>
<%= @message_item %>
</div>
</div>
"""
end
end