I’m starting a new project where I am planning on having both JSON and HTML endpoints. I’ve been looking into some of the best ways to prevent code duplication across two separate sets of controllers, one for each response type. I think this might be the most straightforward way of going about having both an API and regular web endpoints, but I wanted to ask and see if there is a better recommended way of doing it.
I noticed that I can let Phoenix decide which templates to render by passing an atom to the template name in the render function instead of a string, which I think is pretty cool and would be a good way to achieve this goal. An example of this would be
render(conn, :index, users: users) instead of separately having
render(conn, "index.html", users: users) and
render(conn, "index.json", users: users).
I have tested this out, and it works well. However, the main issue I am running into is with the html-specific parts of the controller. In the case of my very very simplistic test project, I experience errors on any API calls to
put_flash/2 or if there is an error with the changeset and a redirect to the
update pages (which obviously don’t exist for the json endpoint). Is there a simple way to structure this such that I can get around these html-specific lines?
I think my options would be to pattern match on the connection and have two separate controller functions (not ideal, logic duplicated) or to have separate controller modules entirely (also not ideal, duplicated code). If the best practice is to separate controller modules, what is the best file/naming structure for this?
I noticed this question is similar to this post, but since it has been 3 years since it was posted I wanted to see if there is an update or consensus to this answer.
- Best practice for controllers that can render both JSON and HTML?
- How to not break JSON endpoints that have calls to
put_flash/2and other html-specific functions?
- If splitting up controllers is the best practice, what should file naming convention be? And project organization? (file structure like
project_web/controllers/html/user_controller.exor something different?)
- a link to an example project on GitHub that does this would be a great bonus