2013-03-12 7 views
7

Ho un paio di modelli in Rails che sembrano qualcosa di simile:oggetti a caricamento laterale con i nomi di classe non-standard in EmberJS con Rails + active_model_serializers

class Issue < ActiveRecord::Base 
    belongs_to :reporter, class_name: 'User' 
    belongs_to :assignee, class_name: 'User' 
    has_many :comments 
end 

class User < ActiveRecord::Base 
end 

class Comment < ActiveRecord::Base 
end 

con serializzatori in questo modo:

class IssueSerializer < ActiveModel::Serializer 
    attributes :id 
    embed :ids, include: true 

    has_one :reporter, :embed => :ids 
    has_one :assignee, :embed => :ids 
end 

class UserSerializer < ActiveModel::Serializer 
    attributes :id, :name 
end 

class CommentSerializer < ActiveModel::Serializer 
    attributes :id, :body 
end 

Questo produce JSON che sembra qualcosa di simile al seguente:

{ 
    "issues": [ 
    { 
     "id": 6, 
     "reporter_id": 1, 
     "assignee_id": 2, 
     "comment_ids": [ 
     3 
     ] 
    }, 
    ], 
    "comments": [ 
    { 
     "id": 3 
     "body": "Great comment" 
    } 
    ], 
    "reporters": [ 
    { 
     "id": 1 
     "name": "Ben Burton" 
    } 
    ], 
    "assignees": [ 
    { 
     "id": 2 
     "name": "Jono Mallanyk" 
    } 
    ] 
} 

il problema è che il giornalisti laterali-caricato e gli oggetti JSON assegnatari non sono riconosciuti dal Ember come oggetti Utente, e vedo il seguente errore:

Uncaught Error: assertion failed: Your server returned a hash with the key reporters but you have no mapping for it 

Non voglio rimuovere

embed :ids, include: true 

dal mio IssueSerializer, perché quindi i commenti non sarebbero serializzati.

ci sono alcuni possibili modi per risolvere questo che ho considerato:

  • Se il metodo embed per ActiveModel :: Serializzatore accettato un elenco di modelli nella sua includere un'opzione, questo potrebbe filtrare la risposta JSON includere solo commenti caricati lateralmente.
  • Il modello dei dati di brace potrebbe essere configurato per caricare gli utenti da "utenti", "reporter" e "assegnatari" ... ma, per quanto posso dire dalla sorgente, sembra che supporti solo una chiave per sideloadAs.
  • In qualche modo ignora/disabilita gli errori di caricamento laterale per le chiavi sconosciute (probabilmente l'approccio meno sano).

C'è un'altra opzione che mi manca qui? Penso che potrei dover scrivere una correzione e inviare una richiesta pull a rails-api/active_model_serializers, emberjs/data o entrambi.

EDIT: La mia soluzione temporanea per questo è di cambiare l'IssueSerializer per serializzare solo gli ID per i reporter e assegnatario:

class IssueSerializer < ActiveModel::Serializer 
    attributes :id, :reporter_id, :assignee_id 
    embed :ids, include: true 

    has_many :comments, :embed => :ids 
end 
+0

Potrebbe mostrare il modello di emissione? –

+0

La tua risposta qui sotto è corretta. – benburton

+0

Quale versione di Ember-data stai usando? –

risposta

1

Si consiglia di leggere this pagina. La sezione di revisione 12 spiega circa il sideloading dei dati dello stesso tipo:

Now, homeAddress and workAddress will be expected to be sideloaded together as addresses because they are the same type. Furthermore, the default root naming conventions (underscore and lowercase) will now also be applied to sideloaded root names.

Il modello dovrebbe essere come:

App.Issue = DS.Model.extend({ 
    reporter: DS.belongsTo('App.User'), 
    assignee: DS.belongsTo('App.User'), 
    comments: DS.hasMany('App.Comment') 
}); 

Il Risultato JSON deve avere una chiave per gli utenti:

{ 
    "issues": [ 
    { 
     "id": 6, 
     "reporter_id": 1, 
     "assignee_id": 2, 
     "comment_ids": [ 
     3 
     ] 
    }, 
    ], 
    "comments": [ 
    { 
     "id": 3 
     "body": "Great comment" 
    } 
    ], 
    "users": [ 
    { 
     "id": 1 
     "name": "Ben Burton" 
    },{ 
     "id": 2 
     "name": "Jono Mallanyk" 
    } 
    ] 
} 

Poiché è stato configurato nel modello che lo reporter è di tipo User, Ember ricerca un utente nel risultato.

+0

La convenzione con cui Ember si aspetta "utenti" come la raccolta di modelli utente caricati lateralmente è incoerente con la convenzione active_model_serializers che gli oggetti sono incorporati al livello superiore con il nome del campo. Sarebbe bello se caricasse gli oggetti User in "utenti", ma non lo facesse. – benburton

+0

La convenzione per active_model_serializers è ancora sulla [roadmap] (https://github.com/emberjs/data#roadmap). Hai ancora il problema con un'altra eccezione? –

+0

La soluzione che ho al momento non è semplicemente quella di caricare gli utenti a parte solo serializzando gli id ​​nel numero (vedi la mia modifica sopra). Questo non è eccezionale, ovviamente, perché è necessaria una seconda richiesta se i modelli utente non sono nel negozio. Dopo aver riflettuto su questo per un po ', penso che ciò che fa Ember sia perfettamente ragionevole. Penso che active_model_serializers abbia un (forse?) Bug nel fatto che sta serializzando i modelli basati sull'alias e non sul nome della classe. – benburton

4

Ho avuto un problema simile e ho trovato una soluzione a ActiveModel::Serializers readme. È possibile utilizzare l'opzione :root.Provare qualcosa di simile per il rilascio serializzatore:

class IssueSerializer < ActiveModel::Serializer 
    attributes :id 
    embed :ids, include: true 

    has_one :reporter, :root => "users" 
    has_one :assignee, :root => "users" 
    has_many :comments 
end 
+0

Questo pulisce gli oggetti caricati lateralmente, quindi se ci sono alcuni reporter utente che non sono assegnatari, non funzionerà. Comunque è utile saperlo. – zode64

0

ho avuto lo stesso problema, aggiungendo include: false sull'associazione ha fatto il trucco per me.

embed :ids, include: true 
    attributes :id, :title 

    has_many :domains, key: :domains, include: false 
    has_many :sessions, key: :sessions