2017-04-22 4 views
0

J'ai 3 tables:Ecto requête de jointure causant (Poison.EncodeError) incapable de coder la valeur

  1. catégories
  2. sous-catégories
  3. categorySubcategories

1 catégorie a 0 à plusieurs sous-catégories.

Je cette fonction qui obtient toutes les entrées de la table des catégories et obtient seulement les entrées de la table des sous-catégories qui appartiennent à la catégorie qui a un identifiant de 1:

def getCategories(conn) do 
    categories = all Api.Category 
    groceryItemSubcategories = from s in Api.Subcategory, 
    join: cs in Api.CategorySubcategory, on: cs.c_id == 1, 
    select: %{name: s.name, foo: cs.c_id} 
    conn 
    |> put_resp_content_type("application/json") 
    |> send_resp(200, Poison.encode!(%{categories: categories, groceryItemSubcategories: groceryItemSubcategories})) 
    end 

donnant cette erreur:

23:10:27.169 [error] #PID<0.339.0> running Api.Router terminated 
Server: localhost:4000 (http) 
Request: GET /categories 
** (exit) an exception was raised: 
    ** (Poison.EncodeError) unable to encode value: {"subcategories", Api.Subcategory} 
     (poison) lib/poison/encoder.ex:383: Poison.Encoder.Any.encode/2 
     (poison) lib/poison/encoder.ex:227: anonymous fn/4 in Poison.Encoder.Map.encode/3 
     (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map."-encode/3-lists^foldl/2-0-"/3 

     (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map.encode/3 
     (poison) lib/poison/encoder.ex:227: anonymous fn/4 in Poison.Encoder.Map.encode/3 
     (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map."-encode/3-lists^foldl/2-0-"/3 

     (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map.encode/3 
     (poison) lib/poison.ex:41: Poison.encode!/2 

La réponse finale est la suivante:

def getCategories(conn) do 
    categories = all Api.Category 
    groceryItemSubcategories = Api.Repo.all(from s in Api.Subcategory, 
    join: cs in Api.CategorySubcategory, on: cs.s_id == s.id, 
    join: c in Api.Category, on: c.id == cs.c_id, 
    where: c.id == 1, 
    select: %{name: s.name, foo: cs.c_id} 
    ) 
    conn 
    |> put_resp_content_type("application/json") 
    |> send_resp(200, Poison.encode!(%{categories: categories, groceryItemSubcategories: groceryItemSubcategories})) 
    end 

La partie qui fait t L'erreur s'en va envelopper la déclaration dans Api.Repo.All(). Dogbert était vraiment celui qui a répondu, donc je ne veux pas répondre à ça.

+0

Poison ne peut pas encoder tuples. Essayez de sélectionner dans une carte, par ex. 'select: {s.name, cs.c_id}' -> 'select:% {nom: s.name, foo: cs.c_id}'. – Dogbert

+0

@Dogbert Merci. Juste posté l'erreur que je reçois quand je fais ça. – BeniaminoBaggins

+0

C'est une erreur de syntaxe. Pourriez-vous poster tout le code que vous avez essayé? Manquant probablement une virgule ou quelque chose quelque part. – Dogbert

Répondre

1

Il y a deux principaux problèmes avec le code d'origine:

  1. Vous avez oublié d'appeler Repo.all dans la deuxième requête.

  2. Vous sélectionnez un tuple dans la requête, puis vous l'encodez en JSON. Poison gère les tuples d'encodage en JSON. Vous pouvez sélectionner une liste ou une carte à la place, en fonction de la structure de données souhaitée. Voici comment choisir une carte:

    groceryItemSubcategories = Api.Repo.all(from s in Api.Subcategory, 
        join: cs in Api.CategorySubcategory, on: cs.s_id == s.id, 
        join: c in Api.Category, on: c.id == cs.c_id, 
        where: c.id == 1, 
        select: %{name: s.name, c_id: cs.c_id})