Phoenix/Elixir - 协议 Enumerable 未实现
Posted
技术标签:
【中文标题】Phoenix/Elixir - 协议 Enumerable 未实现【英文标题】:Phoenix/Elixir - protocol Enumerable not implemented 【发布时间】:2017-07-01 15:49:27 【问题描述】:免责声明:我是 Phoenix 和 Elixir 的新手
我正在尝试创建一个非常基本的 API,用于查询后端 mysql 数据库并获取单个记录、编码为 JSON 并返回。
我有一个现有的 MySQL 数据库,它是现有 Python 应用程序的一部分,我想在 Phoenix 中重构该应用程序,但保持数据库不变,并让新的 Phoenix 应用程序连接并查询它。
所以由于数据库已经存在并且我没有创建新架构,因此我为每个表定义了我的架构并将它们放在我的 /lib 目录中。
我正在尝试查询 TestResultDetail 表并获取给定序列号的最后一条记录。 TestResultDetail 表与包含父记录的 TestResult 表具有多对一关系。
我收到以下错误,不知道如何补救:
在 GET /api/v2/opt/last-result/113325-1002 处出现 Protocol.UndefinedError #Ecto.Query 未实现协议可枚举
应用结构:
这是我对发生错误的看法:
defmodule Webservices.OPTView do
use Webservices.Web, :view
def render("index.json", %results: results) do
%
results: Enum.map(results, &result_json/1)
end
def render("last.json", %results: results) do
%
results: Enum.each(results, &last_result_json/1)
end
def result_json(result) do
%
id: result.id,
serial: result.serial,
date_added: result.date_added
end
def last_result_json(result) do
%
serial: result.serial,
station: result.station,
stage: result.stage,
operator: result.operator,
revision: result.sequence_rev
end
end
这是我的架构:(lib/opt_test_result_detail.ex)
defmodule Webservices.TestResultDetail do
use Ecto.Schema
import Ecto.Query
schema "test_result_detail" do
field :status_id, :integer
field :station_id, :integer
field :stage_id, :integer
field :operator_id, :integer
field :failstep, :string
field :shift, :integer
field :sequence_rev, :integer
field :date_added, Ecto.Date
field :date_timestamp, Ecto.DateTime
field :date_time, Ecto.Time
field :stage_order, :integer
field :serial_number, :string
field :is_retest, :integer
field :retest_reason, :string
has_many :result_id, Webservices.TestResult
end
# fetch last recorded test result for a serial
def last_completed_test(serial) do
from c in Webservices.TestResultDetail,
join: t in TestResult, on: t.id == c.result_id,
select: t.serial, c.station_id, c.stage_id, c.operator_id, c.sequence_rev,
where: t.serial == ^serial,
order_by: [desc: c.id],
limit: 1
end
end
我的控制者:
defmodule Webservices.OPTController do
use Webservices.Web, :controller
alias Webservices.Router
import Webservices.Router.Helpers
# this is the main controller
# def index(conn, %"serial" => serial) do
# import Ecto.Query
#
# results = Webservices.TestResult
# |> where([p], p.serial == serial)
# |> Webservices.Repo.all
#
# render(conn, "index.json", results: results)
#
# end
def last(conn, %"serial" => serial) do
import Ecto.Query
results = Webservices.TestResultDetail.last_completed_test(serial)
render(conn, "last.json", results: results)
end
end
【问题讨论】:
显示控制器。可能您忘记通过Repo.one
传递查询。
抱歉,更新了我的控制器
【参考方案1】:
在您看来,您忘记拨打Repo.one/1
:
results = Webservices.TestResultDetail.last_completed_test(serial)
|> Repo.one
不过,稍微重构一下代码会更好
def last_completed_test(serial) do
from c in __MODEL__,
join: t in assoc(c, :results)
order_by: [desc: c.id],
where: t.serial == ^serial
end
我也相信这一点:
has_many :result_id, Webservices.TestResult
应该是这样的
belongs_to :results, Webservices.TestResult
【讨论】:
对于 Repo.one 的更改,您提到了我的观点,它不应该在控制器中吗?假设您确实是这个意思,我更新了我的控制器(见上文)并且我在 GET /api/v2/opt/last-result/113325-1002 函数 TestResult.__schema__/1 处收到以下错误 UndefinedFunctionError 未定义(模块 TestResult 是不可用) 另外请注意,TestResultDetail 模型与 TestResult 表具有 FK (ManyToOne) 关系。每个父 TestResult 记录会有很多 TestResultDetail 记录。以上是关于Phoenix/Elixir - 协议 Enumerable 未实现的主要内容,如果未能解决你的问题,请参考以下文章
从 Phoenix / Elixir GET 函数中调用 Typescript 函数
使用 Webpack 将语义 UI 添加到 Phoenix v1.4.3