Problem Argument error

ecto
phoenix
#1

Gentlemen, I’m going through a problem.
I’m not able to show the “phoenix” on the screen the values he finds.
Below I will detail how my files are, with the error.

What could it be?

  def list_cdr do
  query_list_cdr = from e in Ecdr,
  select: [e.calldate, e.accountcode, e.amaflags, e.billsec, e.channel, e.clid, e.dcontext, e.disposition, e.dst, e.dstchannel, e.duration, e.lastapp, e.lastdata, e.src, e.uniqueid, e.userfield], limit: 1

  Repo.all(query_list_cdr)
  end

Controller:

  def index(conn, _params) do
    cdr = Structure.list_cdr()
    render(conn, "index.html", cdr: cdr)
  end

Template index (pattern):

<table>
  <thead>
    <tr>
      <th>Calldate</th>
    </tr>
   </thead>
  <tbody>
<%= for ecdr <- @cdr do %>
    <tr>
      <td><%= ecdr.calldate %></td>
    </tr>
</tbody>
  </table>

Error image:
Captura%20de%20tela%20de%202019-06-11%2022-32-50

#2

All examples that select more than a single value in the Ecto.Query docs use tuples, not a list in the :select.

from e in Ecdr,
  select: {e.calldate, e.accountcode, e.amaflags, e.billsec, e.channel, e.clid, e.dcontext, e.disposition, e.dst, e.dstchannel, e.duration, e.lastapp, e.lastdata, e.src, e.uniqueid, e.userfield},
  limit: 1

Edit

Also showing the full stack trace might help us to see what the problem was. It should have been printed into the terminal that runs your application.

#3

That, maybe it might help.

[info] GET /cdr
[debug] Processing with GcallWeb.EcdrController.index/2
  Parameters: %{}
  Pipelines: [:browser]
[debug] QUERY OK source="cdr" db=7.4ms decode=9.0ms queue=1.4ms
SELECT c0.`calldate`, c0.`accountcode`, c0.`amaflags`, c0.`billsec`, c0.`channel`, c0.`clid`, c0.`dcontext`, c0.`disposition`, c0.`dst`, c0.`dstchannel`, c0.`duration`, c0.`lastapp`, c0.`lastdata`, c0.`src`, c0.`uniqueid`, c0.`userfield` FROM `cdr` AS c0 LIMIT 1 []
[info] Sent 500 in 554ms
[error] #PID<0.416.0> running GcallWeb.Endpoint (connection #PID<0.414.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /cdr
** (exit) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.apply({~N[2017-01-04 18:22:36], "", 3, 3, "SIP/172.26.158.1-00000000", "\"\" <000000000000>", "default", "00000", "00000", "", 4, "000", "000000", "0000000000", "00000000000", ""}, :calldate, [])
        (gcall) lib/gcall_web/templates/ecdr/index.html.eex:29: anonymous fn/3 in GcallWeb.EcdrView."index.html"/1
        (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
        (gcall) lib/gcall_web/templates/ecdr/index.html.eex:27: GcallWeb.EcdrView."index.html"/1
        (gcall) lib/gcall_web/templates/layout/app.html.eex:26: GcallWeb.LayoutView."app.html"/1
        (phoenix) lib/phoenix/view.ex:399: Phoenix.View.render_to_iodata/3
        (phoenix) lib/phoenix/controller.ex:729: Phoenix.Controller.__put_render__/5
        (phoenix) lib/phoenix/controller.ex:746: Phoenix.Controller.instrument_render_and_send/4
        (gcall) lib/gcall_web/controllers/ecdr_controller.ex:1: GcallWeb.EcdrController.action/2
        (gcall) lib/gcall_web/controllers/ecdr_controller.ex:1: GcallWeb.EcdrController.phoenix_controller_pipeline/2
        (gcall) lib/gcall_web/endpoint.ex:1: GcallWeb.Endpoint.instrument/4
        (phoenix) lib/phoenix/router.ex:275: Phoenix.Router.__call__/1
        (gcall) lib/gcall_web/endpoint.ex:1: GcallWeb.Endpoint.plug_builder_call/2
        (gcall) lib/plug/debugger.ex:122: GcallWeb.Endpoint."call (overridable 3)"/2
        (gcall) lib/gcall_web/endpoint.ex:1: GcallWeb.Endpoint.call/2
        (phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:33: Phoenix.Endpoint.Cowboy2Handler.init/2
        (cowboy) /home/gilberto/Testes/Elixir/gcall/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy) /home/gilberto/Testes/Elixir/gcall/deps/cowboy/src/cowboy_stream_h.erl:296: :cowboy_stream_h.execute/3
        (cowboy) /home/gilberto/Testes/Elixir/gcall/deps/cowboy/src/cowboy_stream_h.erl:274: :cowboy_stream_h.request_process/3
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
[info] Replied phoenix:live_reload :ok
#4

If you want this to work you either need to return a struct (do not use a select statement at all), or specify field names in your select e.g.

select: %{calldate: e.calldate, accountcode: e.accountcode ... }
#5

Yeah, now I see the problem, as I have the full trace…

ecdr.calldate (as ecdr is not a map) gets expanded to :erlang.apply(ecdr, :calldate, []), which can not work, as ecdr is not an atom as well.

As @jeremyjh said, you need to return something from the query, that supports struct syntax for field access, currently only a map with atom keys supports this syntax.

So why not simply select: e?

1 Like
#6

@jeremyjh I did as requested, but it returns error

Compiling 2 files (.ex)

== Compilation error in file lib/gcall/structure.ex ==
** (SyntaxError) lib/gcall/structure.ex:122: syntax error before: calldate
(elixir) lib/kernel/parallel_compiler.ex:208: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

  def list_cdr do
  query_list_cdr = from e in Ecdr,
  select: {calldate: e.calldate, accountcode: e.accountcode, amaflags: e.amaflags, billsec: e.billsec, channel: e.channel, clid: e.clid, dcontext: e.dcontext, disposition: e.disposition, dst: e.dst, dstchannel: e.dstchannel, duration: e.duration, lastapp: e.lastapp, lastdata: e.lastdata, src: e.src, uniqueid: e.uniqueid, userfield: e.userfield}, limit: 1

  Repo.all(query_list_cdr)
  end

@NobbZ
How would I do that, I’m a little lost?

#7

Sorry, its a map, it needs a %, I’ll edit my post. But @Nobbz is right you can also just select: e here, or leave out the select entirely as that is the default.

2 Likes
#8

@jeremyjh probably had a typo and meant to select: %{...}. And I have not much knowledge about the query DSL, but for me it seems as if you want most, if not all, fields anyway.

I’m pretty sure ecto has some way to express the equivalent of select *

1 Like
#9

Your query is perfectly legal, but it returns a list (array) of items, and when you do Repo.all(query_list_cdr) you get a list of lists. That’s why ecdr.calldate throws error because you can’t access list item like that. I think maybe you mixed up the syntax with another language.

#10

I ended up adding column by column because there are some fields that I do not want it to show.

All of you are correct,
thank you all

Solved with

select: %{calldate: e.calldate ... }

#11

FYI you can simplify this further by doing select: struct(e, [:calldate, :accountcode, :amaflags, ...]

https://hexdocs.pm/ecto/Ecto.Query.html#select/3

2 Likes