Reputation: 75740
I'm trying to return some JSON Data in one of my API Calls in Phoenix. I'm fetching all records of Subject
and sending them but Ecto
returns some extra fields that I do not want.
What can I do to:
id
and name
)__meta__
and __owner__
)This is my Controller
:
# Controller
def index(conn, _) do
subjects = Subject |> Repo.all
conn |> render subjects: subjects
end
This is my View
:
# View
def render("index.json", %{subjects: subjects}) do
subjects
end
This is my response:
[
{
"teachers": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "teachers",
"__cardinality__": "many"
},
"updated_at": "2015-06-20T15:32:20Z",
"topics": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "topics",
"__cardinality__": "many"
},
"name": "Physics",
"inserted_at": "2015-06-20T15:32:20Z",
"id": 1,
"__meta__": {
"state": "loaded",
"source": "subjects"
}
},
{
"teachers": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "teachers",
"__cardinality__": "many"
},
"updated_at": "2015-06-20T15:37:59Z",
"topics": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "topics",
"__cardinality__": "many"
},
"name": "Chemistry",
"inserted_at": "2015-06-20T15:37:59Z",
"id": 2,
"__meta__": {
"state": "loaded",
"source": "subjects"
}
},
{
"teachers": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "teachers",
"__cardinality__": "many"
},
"updated_at": "2015-06-20T15:38:41Z",
"topics": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "topics",
"__cardinality__": "many"
},
"name": "Mathematics",
"inserted_at": "2015-06-20T15:38:41Z",
"id": 3,
"__meta__": {
"state": "loaded",
"source": "subjects"
}
},
{
"teachers": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "teachers",
"__cardinality__": "many"
},
"updated_at": "2015-06-22T15:40:17Z",
"topics": {
"__owner__": "Elixir.MyApp.Subject",
"__field__": "topics",
"__cardinality__": "many"
},
"name": "Biology",
"inserted_at": "2015-06-22T15:40:17Z",
"id": 4,
"__meta__": {
"state": "loaded",
"source": "subjects"
}
}
]
Upvotes: 8
Views: 5919
Reputation: 1670
I use the following macro in MyApp.Repo
, which provides a reusable way to pluck specific fields:
defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.Postgres
import Ecto.Query, warn: false, only: [select: 2]
def pluck(query, fields) when is_atom(fields) do
pluck(query, [fields])
end
def pluck(query, fields) when is_list(fields) do
query |> select(^fields) |> all |> Enum.map(&Map.take(&1, fields))
end
end
Example usage:
my_query |> MyApp.Repo.pluck([:id, :inserted_at])
my_query |> MyApp.Repo.pluck(:id)
Upvotes: 0
Reputation: 1030
Change your view to:
def render("index.json", %{subjects: subjects}) do
Enum.map(subjects, &Map.take(&1, [:id, :name]))
end
Additionally, you can also ask Ecto to return a subset of fields by changing your controller to:
def index(conn, _) do
subjects = from(s in Subject, select: %{id: s.id, name: s.name}) |> Repo.all
conn |> render subjects: subjects
end
Upvotes: 15