0
votes

Disclaimer: I am new to Phoenix and Elixir

I am attempting to create a pretty basic API that queries a backend MySQL database and fetches a single record, encodes to JSON and returns.

I have an already existing MySQL database that is part of an existing Python application, I want to refactor the application in Phoenix but keep the database as is and have the new Phoenix application connect to and query it.

So being the database already exists and I am not creating a new schema I defined my schema's for each table and put them in my /lib directory.

I am trying to query the TestResultDetail table and get the last record for a given serial number. The TestResultDetail table has a ManyToOne relationship with the TestResult table which contains the parent record.

I am getting the following error and not sure how to remedy:

Protocol.UndefinedError at GET /api/v2/opt/last-result/113325-1002 protocol Enumerable not implemented for #Ecto.Query

Error Message

Application Structure:

enter image description here

Here is my view where the error is occurring:

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

Here is my Schema: (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

My Controller:

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
1
Show controller. Probably you have forgotten to pass query through Repo.one.Hauleth
Sorry about that, updated my controllerxXPhenom22Xx

1 Answers

1
votes

You have forgotten to call Repo.one/1 in your view:

results = Webservices.TestResultDetail.last_completed_test(serial)
          |> Repo.one

However it would be better refactor your code a little

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

Also I believe that this:

has_many :result_id, Webservices.TestResult

Should look like

belongs_to :results, Webservices.TestResult