Poison encode nested struct with circular association



Hey :slight_smile:
I’ve got a little problem with encoding my structs as json with Poison. I have a module called Task which can have other Tasks as dependencies, looking like this:

@derive {Poison.Encoder, only: [:name, :dependencies, :costs]}
 schema "task" do
     field :name, :string
     has_many :costs, App.Cost
     has_many :dependencies, App.Dependency, on_replace: :delete

@derive {Poison.Encoder, only: [:value, :task_dependency]}
schema "dependency" do
    field :value, :integer
    belongs_to :task, App.Task
    belongs_to :task_dependency, App.Task

In my frontend I want to show Tasks and their corresponding Task, which they are dependent on. So I take all my tasks and preload(task_dependencies: :task_dependency) and preload(:costs).
On my local machine there is no error but if I push this to Heroku the Application crashes at this point with
"** (RuntimeError) cannot encode association :dependencies from App.Task to JSON because the association was not loaded. because @derive says to encode ‘costs’ of the associated tasks.

So, my solution at this point is to manually Map.drop(:costs) from the associated task to bypass this, but it leads to other problems later on.

So, is there any smarter solution to this or is it even a horrible idea to associate a struct to its own module?


When you fetch for a specific association that association is not preloaded by default. You need to specify which association you will need to use in the future.

ref https://hexdocs.pm/ecto/Ecto.Repo.html#c:preload/3

you can cast what you need to show or serve as a simple map on the view, that’s the more accurate way, specially if you are serving a json api


Thanks pesnk,

sure thing, but the problem is that - even if I preload everything from the dependencies, those (dependency) Tasks can have dependencies themselves, because they are all of the same schema (there is the circular reference between themselves). So I would need to preload those too and I dont know how many levels of nested depencies there are. On the second hand, I dont need that data either.


Not really an expert on ecto preloads, but I’d still stick on setting a limit in your view layer or before that. Don’t even known how ecto would preload cyclic dependencies,