Render different formats in Phoenix
EDIT : In fact Phoenix.Controller.render accepts an atom (ex : :index) for the template, and chooses the format accordingly. So you can write render(conn, :index, posts: posts) without using get_format.
See here and there.
Say I have a Post resource. I define a /posts route. Then, using the same URL, I want to be able to get either a HTML response or a JSON one.
I can ask Phoenix for a specific format either by setting the Accept header, or by passing a _format param, for instance using the url /posts?_format=json. The format can then be fetched using Phoenix.Controller.get_format/1.
The index action (/posts) looks initially like this :
def index(conn, _params) do
posts = Post |> Repo.all()
render conn, "index.html", posts: posts
end
The first step is to add “json” to the :accepts plug in the router :
pipeline :browser do
plug accepts, ["html", "json"]
...
end
Then I add a render(“index.json”, assigns) function to PostView :
def render("index.json", %{posts: posts}) do
posts
|> Enum.map(fn post -> Map.take([:title, :body]) end)
end
Finally I change the index action :
def index(conn, _params) do
posts = Repo.all(Post)
render conn, "index." <> get_format(conn), posts: posts
end
Now if I visit /posts?_format=json I get the appropriate format. /posts doesn’t change : it renders HTML.