2013-03-12 2 views
7

ich ein paar Modelle in Rails haben, die wie folgt aussehen:Side-Laden von Objekten mit Nicht-Standard-Klassennamen in EmberJS mit 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 

mit Serializer wie so:

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 

Dies erzeugt JSON, die etwa wie folgt aussieht:

{ 
    "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" 
    } 
    ] 
} 

das Problem ist, dass die Seite belasteter Reporter und Abtretungs JSON-Objekte werden nicht von Ember als Benutzerobjekte erkannt, und ich sehe die folgenden Fehler:

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

Ich will nicht

embed :ids, include: true 

von meinem IssueSerializer entfernen, weil dann die Kommentare nicht serialisiert würden.

Es gibt einige mögliche Wege, dies zu lösen, die ich in Betracht gezogen habe:

  • Wenn die einbetten Methode für ActiveModel :: Serializer eine Liste von Modellen in seiner umfassen Option akzeptiert, könnte dies die JSON-Antwort-Filter nur seitengeladene Kommentare enthalten.
  • Ember Datenmodell könnte konfiguriert werden, um Benutzer von "Benutzern", "Reportern" und "Beauftragten" zu laden ... aber soweit ich von der Quelle weiß, scheint es nur einen Schlüssel für sideloadAs zu unterstützen.
  • Irgendwie ignorieren/deaktivieren Side-Lade-Fehler für unbekannte Schlüssel (wahrscheinlich der am wenigsten vernünftige Ansatz).

Gibt es eine andere Option, die ich hier vermisse? Ich denke, dass ich eine Reparatur schreiben muss und eine Pull-Anfrage entweder an rails-api/active_model_serializers, emberjs/data oder an beide senden muss.

EDIT: Meine vorübergehende Lösung hierfür ist die IssueSerializer zu ändern, um nur die IDs für Reporter und Abtretungsempfänger zu serialisiert:

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

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

Können Sie Ihr Issue Model zeigen? –

+0

Ihre Antwort unten hat es richtig gemacht. – benburton

+0

Welche Version von Ember-Daten verwendest du? –

Antwort

1

Sie this Seite lesen sollte. Der Abschnitt der Revision 12 erklärt über die sideloading von Daten des gleichen Typs:

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

Das JSON Ergebnis einen Schlüssel für die Benutzer haben sollte:

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.

Ihr Modell sein sollte

{ 
    "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" 
    } 
    ] 
} 

Da Sie in Ihrem Modell konfiguriert haben, dass der reporter vom Typ User ist, suchen Ember nach einem Benutzer im Ergebnis.

+0

Die Konvention, dass Ember "Benutzer" als die side-loaded Sammlung von Benutzermodellen erwartet, widerspricht der Active_model_serializers Konvention, dass die Objekte auf der obersten Ebene mit dem Feldnamen eingebettet sind. Es wäre toll, wenn User-Objekte unter "Benutzer" ausgelagert würden, aber nicht. – benburton

+0

Die Konvention für active_model_serializers befindet sich noch auf der [roadmap] (https://github.com/emberjs/data#roadmap). Haben Sie das Problem noch mit einer anderen Ausnahme? –

+0

Die Lösung, die ich im Moment habe, besteht einfach darin, die Benutzer überhaupt nicht zu seiten, indem ich nur die IDs im Issue serialisiere (siehe meine Bearbeitung oben). Dies ist offensichtlich nicht großartig, da eine zweite Anfrage benötigt wird, wenn die Benutzermodelle nicht im Laden sind. Nachdem ich eine Weile darüber nachgedacht habe, denke ich, dass das, was Ember macht, vollkommen vernünftig ist. Ich denke, dass active_model_serializers einen (vielleicht?) Fehler hat, indem es die Modelle auf der Grundlage des Alias ​​und nicht des Klassennamens serialisiert. – benburton

4

Ich hatte ähnliches Problem und habe Lösung bei ActiveModel::Serializers readme gefunden. Sie können die Option :root verwenden.Versuchen Sie so etwas wie dies für Ausgabe Serializer:

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

Dadurch werden die zuvor geladenen Objekte gelöscht. Wenn also einige Benutzerreporter nicht zugewiesen sind, funktioniert das nicht. Trotzdem ist es nützlich zu wissen. – zode64

0

ich das gleiche Problem hat, das Hinzufügen include: false über die Assoziation für mich den Trick.

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

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