将数据从模型/数据库传递到使用的存在



我有一个简单的聊天应用程序,我希望能够在频道的HTML页面上的用户名旁边显示用户上传的图像(本地托管(。当前,我正在使用存在来跟踪登录到频道等的用户。我能够覆盖fetch/2功能,以了解它可以让我在:metas符号中使用用户模型数据添加几个MAP字段。

我可以根据每个功能的不同部分的广泛IO.inspecting所说的;fetch/2handle_info/2和一些控制台。在我的JS层上插入,fetch/2函数实际上并未从数据库中获取任何数据,也没有将其分配给:metas MAP。

这是我当前的fetch/2功能:

def fetch(_topic, entries) do
  query =
    from u in User,
      where: u.id in ^Map.keys(entries),
      select: {u.id, u}
  users = query |> Repo.all |> Enum.into(%{})
  for {key, %{metas: metas}} <- entries, into: %{} do 
    {key, %{metas: metas, user: users[key]}}
end

基本上是直接从文档中撕下的。从理论上讲,上面的功能应查询我的用户模型,并基于通过条目映射传递给它的User.id获取所有用户数据。尽管users是我用户模型的完整地图,但Users[keys]还是空的。

此外,根据文档,查询只能在加入上运行,以免超载DB,但每次我刷新页面时似乎都会运行4-5次。要注意的另一件事是,条目内部的user.id似乎是字符串类型。我不确定这是否重要,我尝试从JS层传递整数,并使用实际fetch/2函数中的Interger.parse将其更改为无用。

当我检查用户地图时,我会得到:

{"1" => %MyApp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, 
email: "test@test.com", encrypt_pass: "$pbkdf2-
sha512$160000$ebfY956TgIXhEAF.mqLJAg$QWzBubfeiy4Xrf‌​.EsFiU0jEZAuKvV4ZO5a‌​
8QpeFr817C61DuaNfyo5‌​6WWzj6jak2homCFWAINb‌​PrFtCSXUPWTw", gravatar: %
{file_name: "logo.png", updated_at: #Ecto.DateTime<2017-04-20 22:00:08>}, 
id: 1, inserted_at: ~N[2017-04-20 22:00:09.071000], password: nil, 
updated_at: ~N[2017-04-20 22:00:09.090000]}}

我的用户[键]返回一个像此%{}这样的空图,并将输入转换为整数会丢弃错误,如果我将其转换为Elixir Code内部,则(Poison.EncodeError) unable to encode value: {nil, "users"},如果我从JS层转换了where: u.id in ^["undefined"], select: {u.id, u} (elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3 –,则CC_17。

原始fetch/2输出是:metas中的online_at: 1492764577562phx_ref: "OAyzaGE82xc="的数组,在users VAR中我的用户ID或电子邮件或电子邮件。

我在这里缺少什么?我知道fetch/2功能仅作为对Presence.list/1函数的回调执行,我在handle_info/2 Channel函数中调用该功能。我还在我的JS层中调用Presence.list并将其映射到我的存在中,以便可以在HTML中产生用户名列表。我只是误解了这是如何工作的,还是还有其他一些更简单的方法?如果您需要查看更多代码,我可以提供更多。

编辑:我对这里发生的事情有更好的了解。我的条目地图实际上是:

%{"1" => %{metas: [%{online_at: 1492798247818, phx_ref: "ELHwA+gWF+0="}]}} 

基本上,用户ID的字符串映射到metas地图上。当我尝试使用Map.keys(entries)函数将该键从地图中取出时,它无法从DB中拉出任何内容,因为它是一个字符串,但是,当我将其更改为JavaScript端的整数时,它会抛出一个错误,因为无论出于何种原因,Phoenix都期望该键是字符串类型。奇怪的是,如果我将idid更改为email,并尝试通过电子邮件查询DB,也无法正常工作。尽管数据库中的电子邮件是字符串,而metas地图期望entries地图的字符串密钥。

我将从头开始重建该频道的一部分,并查看导致此问题的原因。然后,我会回来看看是否能够解决错误。

您应该先验证条目中的键。

ids = Map.keys(entries)
true = Enum.all?(ids, &is_integer/1)

ecto将字符串插值转换为查询时的整数:

iex(40)> Ecto.Query.from(u in Users, where: u.id in ^[1, 2, "3", nil], select: u.id) |> Repo.all()

输出以下调试日志:

[debug] QUERY OK source="users" db=0.8ms
SELECT u0."id" FROM "users" AS r0 WHERE (r0."id" = ANY($1)) [[1, 2, 3, nil]]

注意,它将字符串" 3"胁迫到整数并允许零。

但是,地图不会那么善良:

iex(42)> users = %{1 => %{name: "joe"}, 2 => %{name: "jill"}}
%{1 => %{name: "joe"}, 2 => %{name: "jill"}}
iex(43)> users["1"]
nil

因此,在您使用entries的键进行数据库查找和地图查找的代码中,它可能会产生不同的结果。

我已经弄清楚了这个问题与我的fetch/2功能本身无关,而是与我在这种情况下的实现模块和渠道有关。基本上,每当有人进入聊天室时,fetch/2功能被称为4次,而在四次中有两个被称为空名单值[]

显然,您无法查询具有空列表的eTeco模型,因此在这种情况下也丢了错误。我尝试将护罩放在获取功能上以滤除空列表调用,但它也不会向我展示我正在寻找的metas地图数据,即使查询成功了。

此外,另一个主要问题是我的实施或缺乏token的实现。如果我使用令牌来加入聊天室,而不是user(又称一个用户名(,则我不必通过Fetch函数metas地图传递用户模型数据。实现这一实现后,我能够成功地将用户模型数据与频道连接并通过JS层显示,并最终将其放在客户端上。

无论如何,谢谢您的建议。您可能没有回答这个问题(这是我提出错误的问题的错(,但是您当然可以帮助我到达那里。还为我提供了对一般框架的更好理解的工具。

如果/当我还有其他问题时,我将确保在将它们发布到堆叠溢出之前,请问我要问正确的问题,这样我就不会浪费时间。

相关内容

  • 没有找到相关文章

最新更新