Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Poison Encode encoding nested models

Sup,

I'm trying to encode some nested Ecto Models but i have encountered a problem. I realised that i can't encode unloaded model and i want to have possibility of selecting only one structure without loading rest and at the same time having possibility of selecting whole tree.

I have used method with defimpl, example:

defimpl Poison.Encoder, for: Hangman.MasterCat do
    def encode(page, _options) do
      %{
        id: page.id,
        name: page.name,
        categories: page.categories
      } |> Poison.Encoder.encode([])
    end
  end
defimpl Poison.Encoder, for: Hangman.Category do
    def encode(category, _options) do
      IO.inspect(category.words)
      %{
        id: category.id,
        name: category.name,
        words: category.words
      } |> Poison.Encoder.encode([])
    end
  end
defimpl Poison.Encoder, for: Hangman.Word do
    def encode(page, _options) do
      %{
        content: page.content
      } |> Poison.Encoder.encode([])
    end
  end

This works for whole structure but it doesn't work for selecting only MasterCats and it gives such error.

cannot encode association :categories from Hangman.MasterCat to JSON because the association was not loaded. Please make sure you have preloaded the association or remove it from the data to be encoded
like image 803
Haito Avatar asked Oct 17 '15 17:10

Haito


1 Answers

You need to define the same encoder for categories too and so on. In fact, there is an easier to do this, if you are using latest Poison, you can write:

defmodule Hangman.MasterCat do
  use Ecto.Model

  @derive {Poison.Encoder, only: [:id, :name, :categories]}
  schema "..." do

This way, Elixir takes care of automatically implementing the protocol for you. As long as you derive the encoder for the types you care, you should be good. For complex cases, explicitly implementing the protocol, as you did, is the way to go.

like image 115
José Valim Avatar answered Sep 24 '22 08:09

José Valim