0
votes

I am trying to create a Phoenix application with generated html as well as json api responses. This is what I have done so far:

mix phoenix.gen.html User users name:string email:string
mix phoenix.gen.json Api.User users --no-model

Then I changed the alias in UserController from "alias MyApp.Api.User" to "alias Api.User". And it works! .. well mostly!

This is what I get in http response:

{"data":[{"id":1},{"id":2}]}

The problem I am trying to fix is - when I call GET on the Api, I just get a list of id's; all other useful fields are not being returned. IO.inspect tells me that controller is returning everything. So it must be the view which is filtering out fields.

However, my understanding of Elixir/Phoenix falls short here. This is what I see:

  def render("index.json", %{users: users}) do
    %{data: render_many(users, MyApp.Api.UserView, "user.json")}
  end

My basic question is - How can I dive in render_many method and find out what is happening to fix this?

My secondary questions are:

  • Is there any good resource to get html and json api's working together in Phoenix?
  • What is "user.json" in the code above? With regards to "index.json", I think it is used only for pattern matching.
2

2 Answers

1
votes

There should be the following code in web/views/api/user_view.ex:

def render("user.json", %{user: user}) do
  %{id: user.id}
end

You just need to add more fields to that:

def render("user.json", %{user: user}) do
  %{id: user.id, name: user.name, email: user.email}
end

or

def render("user.json", %{user: user}) do
  Map.take(user, [:id, :name, :email])
end

The documentation explains how Phoenix.View.render_many/4 works in detail.

Is there any good resource to get html and json api's working together in Phoenix?

I'm not aware of any.

What is "user.json" in the code above? With regards to "index.json", I think it is used only for pattern matching.

Yes, that parameter is passed to render by render_many. See the documentation link above.

0
votes

Is there any good resource to get html and json api's working together in Phoenix?

If your html and json use the same resource & logic, and they probably should, you can do the following:

In your view, define both ".html" and ".json" clauses, e.g.

def render("show.json", %{user: user}) do
  %{...}
end

def render("show.html", %{user: user}) do
  render ...
end

In your controller, change the string, e.g. "show.html", to an atom without the suffix, e.g. :show

In your router, make sure you accept both html and json in your pipeline

And phoenix should render the responses in the according format when requests come in.