【问题标题】:Poison.Encoder how to preload associations?Poison.Encoder 如何预加载关联?
【发布时间】:2018-03-15 17:59:58
【问题描述】:

我有下面的 Ecto 型号。当我尝试渲染时出现错误。如何修改@derive 以便预加载?还是我必须写出实现?处理此问题的推荐方法是什么?

** (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

模型在这里:

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

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    简短的回答是您不应该这样做。预加载数据不是视图层的责任。

    您应该在获取资源(通常是控制器或从控制器调用的函数)时执行预加载。

    例如使用Ecto.Repo.preload/3:

    def index(_conn, _params)
      timemaps = Tilemap |> Repo.all() |> Repo.preload(:timemap_layers)
      render("index.json", tilemaps: tilemaps)
    end
    

    您还可以使用Ecto.Query.preload/3 在查询中执行预加载:

    query = from t in Tilemap,
      preload: [:tilemap_layers]
    Repo.all(query)
    

    【讨论】:

    • 谢谢 Gazler,现在说得通了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多