3
votes

I have a simple Todo/Author/Comment

Todo has_many comments
Comment belongs_to Todo
Todo belongs_to Author
Author has_many todos
Author has_many comments
Comment belongs_to Author

If I render the todo_view.ex like this:

  def render("todo.json", %{todo: todo}) do
    %{id: todo.id,
      title: todo.title,
      description: todo.description,
      date: todo.date,
      author: author_json(todo.author)}
  end
  defp author_json(author) do
    %{name: author.name}
  end

Everything works fine when I access /api/todos and /api/comments But if I want to add the list of comments for the todos:

  def render("todo.json", %{todo: todo}) do
    %{id: todo.id,
      title: todo.title,
      description: todo.description,
      date: todo.date,
      author: author_json(todo.author),
      comments: render_many(todo.comments, CommentView, "comment.json")}
  end

I get a KeyError in comment_view.ex

key :name not found in: #Ecto.Association.NotLoaded

  def render("comment.json", %{comment: comment}) do
    %{id: comment.id,
      content: comment.content,
      author: author_json(comment.author)}
  end
  defp author_json(author) do
    %{name: author.name}
  end

Somehow Elixir doesn't see the Comment / Author association when querying todos, but it does see it when querying comments.

I did the preloading for comment:

comments = Repo.all(Comment) |> Repo.preload(:author)

Any idea what's happening here?

1

1 Answers

5
votes

Did you preload author when you fetched the todos from the database? Something like this:

todos = Todo |> Repo.all() |> Repo.preload([comments: [:author]])

This loads for all ToDos the Comments with their Author associations.