无法将聊天消息从 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