问题
I have the Ecto model below. When I try to render I get an error. How can I modify the @derive so it will preload? Or do I have to write out the implementation? What is the recommended way of dealing with this?
** (RuntimeError) cannot encode association :tilemap_layers from MyProject.Tilemap 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
The model is here:
defmodule MyProject.Tilemap do
use MyProject.Web, :model
@derive {Poison.Encoder, only: [
:name,
:tile_width,
:tile_height,
:width,
:height,
:orientation,
:tilemap_layers,
:tilesets
]}
schema "tilemaps" do
field :name, :string
field :tile_width, :integer
field :tile_height, :integer
field :width, :integer
field :height, :integer
field :orientation, :string
has_many :tilemap_layers, MyProject.TilemapLayer
has_many :tilesets, MyProject.Tileset
timestamps
end
@required_fields ~w(tile_width tile_height width height)
@optional_fields ~w()
@doc """
Creates a changeset based on the `model` and `params`.
If no params are provided, an invalid changeset is returned
with no validation performed.
"""
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
回答1:
The short answer is you shouldn't. Preloading the data is not the responsibility of the view layer.
You should perform the preload when you are fetching your resource (usually the controller or a function called from the controller.)
For example using Ecto.Repo.preload/3:
def index(_conn, _params)
timemaps = Tilemap |> Repo.all() |> Repo.preload(:timemap_layers)
render("index.json", tilemaps: tilemaps)
end
You can also perform a preload in a query with Ecto.Query.preload/3:
query = from t in Tilemap,
preload: [:tilemap_layers]
Repo.all(query)
来源:https://stackoverflow.com/questions/33756142/poison-encoder-how-to-preload-associations