【问题标题】:Phoenix/Elixir - protocol Enumerable not implementedPhoenix/Elixir - 协议 Enumerable 未实现
【发布时间】: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 传递查询。
  • 抱歉,更新了我的控制器

标签: elixir phoenix-framework ecto


【解决方案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 记录。
猜你喜欢
  • 2017-04-19
  • 1970-01-01
  • 2015-09-03
  • 2016-09-17
  • 2017-12-11
  • 2017-11-26
  • 2018-02-11
  • 2016-05-09
  • 2018-11-23
相关资源
最近更新 更多