elixir - 使用 Ecto 在 Elixir 的测试中有时会出现奇怪的错误
问题描述
错误:
14:18:04.259 [error] GenServer MyApp.Receiver.Handlers terminating
** (Ecto.Query.CastError) deps/ecto/lib/ecto/repo/queryable.ex:382: value `1234` in `where` cannot be cast to type :string in query:
from c0 in MyApp.DB.Client,
where: c0.client_id == ^1234,
select: c0
(elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/enum.ex:1431: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto) lib/ecto/repo/queryable.ex:138: Ecto.Repo.Queryable.execute/4
(ecto) lib/ecto/repo/queryable.ex:18: Ecto.Repo.Queryable.all/3
(ecto) lib/ecto/repo/queryable.ex:67: Ecto.Repo.Queryable.one/3
(my_app) lib/my_app/db/db_impl/db_impl.ex:54: MyApp.DBImpl.add_update_client/1
(my_app) lib/my_app/receiver/receiver_handlers.ex:23: MyApp.Receiver.Handlers.handle_cast/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:add_update_client, %{client_id: 1234, client_pid: #PID<0.408.0>}}}
State: %{}
@doc """
Client connects or reconnects
"""
def add_update_client(client) do
%{client_id: client_id} = client
# This is the line causing the error
client_db = DB.Client |> Repo.get_by(client_id: client_id)
create_update_client(client_db, client)
end
defmodule MyApp.DB.Client do
use Ecto.Schema
schema "client" do
field :client_id, :string
field :client_pid, :binary
timestamps()
end
# This says how you can change a record
def changeset(client, params \\ %{}) do
client
|> Ecto.Changeset.cast(params, [:client_id, :client_pid])
# Use validation if need be
|> Ecto.Changeset.validate_required([:client_id, :client_pid])
end
def update_client_pid_changeset(client, params \\ %{}) do
client
|> Ecto.Changeset.cast(params, [:client_pid])
# Use validation if need be
|> Ecto.Changeset.validate_required([:client_pid])
end
end
defmodule MyApp.Repo.Migrations.CreateClient do
use Ecto.Migration
def change do
create table(:client) do
add :client_id, :string
add :client_pid, :binary
timestamps
end
end
end
我尝试将故障线更改为此但仍然收到相同的错误:
client_db = Repo.one(from c in DB.Client,
where: c.client_id == type(^client_id, :string)
)
我用于 client_id 的值是数字字符串,例如“1234”,但有时Ecto 无法弄清楚。这只发生在 1/10 左右的测试中。据我所知,它在代码正常运行时一直有效。我怀疑这与测试运行的顺序有关,但我不确定。其他人有类似的问题和潜在的解决方案吗?
编辑:我认为正在发生的事情是代码“1234”中的某处变成了1234。我不知道这是如何或为什么会发生的。我从 json 文件中提取这些值,所以我认为它可能来自解析器,但似乎没有发生。此外,所有值都可以毫无问题地插入到数据库中。它在更新时触发了变更集错误,因此代码以某种方式将字符串解析为数字。
已解决:我之前编写的一个 doctest 触发插入数据库,我在 doctest 中使用 1234 而不是正确使用“1234”,所以这一直是我的错误。
解决方案
试试这个怎么样:
插值时,您可能需要明确告诉 Ecto 被插值的预期类型是什么:
age = "18" Repo.all(from u in "users", where: u.age > type(^age, :integer), select: u.name)
推荐阅读
- vue.js - Vue - 如何在 Vue 组件中呈现 HTML
- java - 接口中的默认方法 - Java
- associations - cakephp 3 - 不可能用空列表生成条件
- typescript - Loopback4 多对多关系,但没有额外的 id 字段作为关系表中的主键
- linux - 在shell脚本中组合匹配的字符串和总和列
- google-apps-script - 我的脚本的项目属性中列出了额外的范围
- customization - 如何将我自己的 CSS 添加到具有现有线框主题的 Sitecore SXA 自定义组件?
- batch-file - Windows批处理文件中变量中的第一个大写字符
- python-3.7 - 无法从 Lark AST 获取值
- reactjs - React 中的条件道具(仅接受 2 个道具中的 1 个)