Preloaded associations and views patterns

I’m wondering how do people structure their JSON Api’s with Phoenix. Using the blogs example, let’s say I have a blogs view like the following

  def render("show.json", %{blog: blog}) do
    %{
      id: blog.id,
      title: blog.title,
      posts: render_many(blog.posts, PostView, "post.json")
    }

This runs into things like what if posts has its own associations like comments, etc.

In my controller maybe sometimes I don’t care about the associations and other times I do. This leads me to two main problems?

  1. Are there any standards people follow to handle when a view should try and render associations?
  2. Should there be some helper function in Phoenix.View that handles conditionally rendering associations?

For the first problem I’m just curious how people do something like the following

  def show(conn, %{"id" => id}) do
    blog = Blogs.get_blog_with_all(id)
    # assume no associations are preloaded
    render(conn, "show.json", blog: blog)
  end

  def some_action(conn, %{"id" => id}) do
    blog = Blogs.get_blog_with_all(id, preload: [:association_one, :association_two])
    # here I want to include the two associations in my view
    render(conn, "show_with_association_one_and_two.json", blog: blog)
  end

Having a specific view for each combination of association seems tedious.

For the second problem I mean something like having a helper function maybe_render_association that will add the field to the view if the association is loaded or it will not include the field at all. My thinking is we don’t want to return nil in the case that the association is not loaded since it’s not actually nil. That pattern would look like


def render() do
  def render("post.json", %{post: post}) do
    %{
      id: post.id,
      title: post.title,
      body: post.body,
      comments: render_many(post.comments, CommentView, "comment.json")
    }
    # it would be nice if we can have it inside the above map but 
    # since it's a conditional field not sure how
    |> maybe_render_association(post.updated_by, :updated_by, User, "basic.json")
  end
end