无法将聊天消息从 Elixir 保存到 PostgreSQL
Cannot save chat messages from Elixir to PostgreSQL
我似乎无法在重新加载时将任何消息持久保存到数据库中。
它不显示任何错误消息。
为代码添加了链接。
room_channel.ex
defmodule Chat.RoomChannel do
use Phoenix.Channel
alias Chat.Presence
alias Chat.Repo
alias Chat.User
alias Chat.Message
def join("room", payload, socket) do
if authorized?(payload) do
send(self(), :after_join)
{:ok, socket}
else
{:error, %{reason: "unauthorized"}}
end
end
def handle_in("new_messages", payload, socket) do
spawn(fn -> save_message(payload) end)
user = Repo.get(User, socket.assigns.user_id)
broadcast! socket, "new_messages", %{user: user.name, message: payload["message"]}
{:noreply, socket}
end
def handle_info(:after_join, socket) do
Message.recent_messages()
|> Enum.each(fn msg -> push(socket, "new_messages", format_msg(msg)) end)
user = Repo.get(User, socket.assigns.user_id)
{:ok, _} = Presence.track(socket, user.name, %{
online_at: inspect(System.system_time(:seconds))
})
push socket, "presence_state", Presence.list(socket)
{:noreply, socket}
end
defp format_msg(msg) do
%{
name: msg.name,
message: msg.message
}
end
defp save_message(message) do
Message.changeset(%Message{}, message) |> Repo.insert
end
defp authorized?(_payload) do
true
end
end
message.ex
defmodule Chat.Message do
use Ecto.Schema
import Ecto.Changeset
schema "messages" do
field :name, :string
field :message, :string
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :message])
|> validate_required([:name, :message])
end
def recent_messages(limit \ 10) do
Chat.Repo.all(Chat.Message, limit: limit)
end
end
mix.exs
defp deps do
[{:phoenix, "~> 1.2.5"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:coherence, "~> 0.3"}]
end
Elixir 1.11.2 (compiled with Erlang/OTP 23)
postgres (PostgreSQL) 13.0
我认为问题出在 room_channel.ex
中的 handle_in 函数上
spawn(fn -> save_message(payload) end)
任何指向正确方向的线索?
在 spawn on handle_in 函数中使用了 %{name: user.name, message: payload["message"]})
。由于有效负载的地图是 %{user: user.name, message: payload["message"]})
,这似乎不起作用。
def handle_in("message:new", payload, socket) do
user = Repo.get(User, socket.assigns.user_id)
spawn(fn -> save_message(%{name: user.name, message: payload["message"]}) end)
broadcast! socket, "message:new", %{user: user.name, message: payload["message"]}
{:noreply, socket}
end
但是刷新后,它仍然获取用户'undefined'。设置以下 format_message 函数解决了该问题。
defp format_msg(msg) do
%{
user: msg.name,
message: msg.message
}
end
我似乎无法在重新加载时将任何消息持久保存到数据库中。
它不显示任何错误消息。
为代码添加了链接。
room_channel.ex
defmodule Chat.RoomChannel do
use Phoenix.Channel
alias Chat.Presence
alias Chat.Repo
alias Chat.User
alias Chat.Message
def join("room", payload, socket) do
if authorized?(payload) do
send(self(), :after_join)
{:ok, socket}
else
{:error, %{reason: "unauthorized"}}
end
end
def handle_in("new_messages", payload, socket) do
spawn(fn -> save_message(payload) end)
user = Repo.get(User, socket.assigns.user_id)
broadcast! socket, "new_messages", %{user: user.name, message: payload["message"]}
{:noreply, socket}
end
def handle_info(:after_join, socket) do
Message.recent_messages()
|> Enum.each(fn msg -> push(socket, "new_messages", format_msg(msg)) end)
user = Repo.get(User, socket.assigns.user_id)
{:ok, _} = Presence.track(socket, user.name, %{
online_at: inspect(System.system_time(:seconds))
})
push socket, "presence_state", Presence.list(socket)
{:noreply, socket}
end
defp format_msg(msg) do
%{
name: msg.name,
message: msg.message
}
end
defp save_message(message) do
Message.changeset(%Message{}, message) |> Repo.insert
end
defp authorized?(_payload) do
true
end
end
message.ex
defmodule Chat.Message do
use Ecto.Schema
import Ecto.Changeset
schema "messages" do
field :name, :string
field :message, :string
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :message])
|> validate_required([:name, :message])
end
def recent_messages(limit \ 10) do
Chat.Repo.all(Chat.Message, limit: limit)
end
end
mix.exs
defp deps do
[{:phoenix, "~> 1.2.5"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:coherence, "~> 0.3"}]
end
Elixir 1.11.2 (compiled with Erlang/OTP 23)
postgres (PostgreSQL) 13.0
我认为问题出在 room_channel.ex
中的 handle_in 函数上spawn(fn -> save_message(payload) end)
任何指向正确方向的线索?
在 spawn on handle_in 函数中使用了 %{name: user.name, message: payload["message"]})
。由于有效负载的地图是 %{user: user.name, message: payload["message"]})
,这似乎不起作用。
def handle_in("message:new", payload, socket) do
user = Repo.get(User, socket.assigns.user_id)
spawn(fn -> save_message(%{name: user.name, message: payload["message"]}) end)
broadcast! socket, "message:new", %{user: user.name, message: payload["message"]}
{:noreply, socket}
end
但是刷新后,它仍然获取用户'undefined'。设置以下 format_message 函数解决了该问题。
defp format_msg(msg) do
%{
user: msg.name,
message: msg.message
}
end