Poison.Encoder how to preload associations?

2019-07-13 04:42发布

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条回答
等我变得足够好
2楼-- · 2019-07-13 05:12

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)
查看更多
登录 后发表回答