2015-11-17 1 views
2

J'ai le modèle Ecto ci-dessous. Quand j'essaie de rendre, j'obtiens une erreur. Comment puis-je modifier le @derive afin qu'il précharge? Ou dois-je écrire la mise en œuvre? Quelle est la manière recommandée de gérer cela?Poison.Encoder comment précharger les associations?

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

Le modèle est ici:

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 

Répondre

3

La réponse courte est que vous ne devriez pas. Le préchargement des données n'est pas la responsabilité de la couche de vue.

Vous devez effectuer la pré-charge lorsque vous récupérez votre ressource

Par exemple en utilisant Ecto.Repo.preload/2 (habituellement le contrôleur ou une fonction appelée du contrôleur.):

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

Vous pouvez également effectuer une pré-charge dans une requête avec Ecto.Query.preload/3:

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

Merci Gazler, c'est logique maintenant! –