Search code examples
elixirphoenix-frameworkecto

How to use Repo.get with select like in Repo.one


I'm not sure this is possible but I like the fact that Repo.get is returning a Struct.

I'm trying to do something like:

Repo.get(User, id, select: [:id, :name])

Like in:

Repo.one(from u in User, where: u.id == ^id, select: [u.id, u.name]

But with Repo.get, I cannot figure out from the Ecto docs if it's possible and how to achieve this.

Context: I'm using Guardian and the serializer does something like:

def from_token("User:" <> id), do: {:ok, Repo.get(User, id,)}

So when I call current_resource(conn) I get a convenient user struct. But this query return all the infos of the user from the db which I'm trying to filter (for instance I don't want the encrypted password in my current_resource(conn).


Solution

  • As @Dogbert mention in the comments the solution is:

    import Ecto.Query
    
    from(User) |> select([:id, :name]) |> Repo.get(id)
    

    And inside the guardian serializer:

    import Ecto.Query
    
    ....
    
    def from_token("User:" <> id), do: {:ok, from(User) |> select([:id, :name]) |> Repo.get(id)}
    
    .....
    

    From the Ecto.Repo docs:

    get(queryable, id, opts) get(queryable :: Ecto.Queryable.t, id :: term, opts :: Keyword.t) :: Ecto.Schema.t | nil | no_return

    Fetches a single struct from the data store where the primary key matches the given id.

    Returns nil if no result was found. If the struct in the queryable has no or more than one primary key, it will raise an argument error.

    As mention the first argument that get/3 is waiting for is a queryable. That's why we can construct the queryable with from(User) |> select([:id, :name]) and then passes it to Repo.get(id)

    This will return a struct based on the user model.

    And as the phoenix-framework docs mentionned:

    Each model defines the fields of our schema as well as their types. They each define a struct with the same fields in our schema.

    So the struct that is returned will have all field described in the model/schema but with nil values where we don't select them.