Getting error in liveview: "errors were found at the given arguments: * 1st argument: not an atom"

In the router:

live "/users", UserLive.Index, :index

In the controller:

 def mount(_params, _session, socket) do
   {:ok, assign(socket, :users, list_users())}
 end```
 defp list_users do
   Accounts.list_users()
 end` from Accounts `
 def list_users() do
   sql = """
     SELECT id, username, first_name, last_name FROM users;
   """
   %Postgrex.Result{rows: rows} = Ecto.Adapters.SQL.query!(Repo, sql)
   List.flatten(rows)
 end

The SQL query is successful and outputs a list of data when inspected. The last file in the stacktrace is the index.html.heex and the specfici line pointed to is this
<%= for user <- @users do %>. This is an auto-generated template and the controller is also auto-generated. The only thing I’ve written was the Accounts.list_users function. Any idea where this bug may be coming from? Thanks in advance!

It’s because your list_users function does not return structs…

and the link helpers (not shown in your code) are not going to be happy.

Why does it have to be a struct? Specifically a struct or does any map type do? Could you please link to that in the documentation, I didn’t see anything about it. Thank you!

I know this because I tried… I did not found this in any documentation.

So how would the struct look… I don’t understand. Right now it’s a big list of data, I’m not sure how I would meaningfully turn that into a struct.

You could use Repo.all instead of building your own query.

You don’t have context?

You need a struct, a map won’t do…

I’m not sure, I’d rather build my own query in this case

You still can, be need to transform the result of your query into list of structs.

and theres no documentation or anything I can read to help with this? how do you turn a list into a list of structs?

You can do it like this.

rows
|> List.flatten()
|> Enum.map(fn [id, uname, fname, lname] -> %User{id: ...} end)

Maybe someone can point You to the right doc. I would look at Phoenix link helpers, and Ecto adapters sql query to structs.

But You should notice You are using your own way, Nobody cares about transforming query results into structs, because it’s what ecto sql do.

Where is the struct coming from? When I try to do that I get User.__struct__/1 is undefined, cannot expand struct User. What would be the right way? I looked at Repo.all but the documentation doesn’t really make sense Ecto.Repo — Ecto v3.7.1

I suppose You know the full name of your User struct. Often I use alias for this…

Ah okay so it’s my user struct. Ok thank you. But again what would be the correct way to do this? I see a bunch of different ways all over the place and the documentation I linked above to Repo.all doesn’t really explain how to use it.

Ecto is difficult, but once You understand it’s close to sql, You’ll start to like it.

alias ...User
alias ...Repo
import Ecto.Query
Repo.all from(u in User)
1 Like

How would I only get certain fields from user like I do in the SQL query?

Repo.all from(u in User, select: [:id, :name])
2 Likes

Ah that makes sense, thank you! Would you have any recommendations for where I can find better documentation of ecto? Like looking at Repo.all on hexdocs I would not have gotten that… Ecto.Repo — Ecto v3.7.1

This one is nice…

https://hexdocs.pm/ecto/Ecto.Query.html

1 Like

thank you