9

Ich schreibe eine Übung Backbone-App, mit Rails Backend-API, und ich bin verwirrt über das Verhalten von Speichern auf Backbone-Modelle.Warum sendet das Backbone-Modell beim Speichern doppelte Attribute an den Server?

Nehmen wir an, ein Team hat viele Spieler, und ich möchte ein Team mit zahlreichen Spielern in einem einzigen POST speichern.

So in Rails Ich habe:

class Team < ActiveRecord::Base 
    has_many :players 
    accepts_nested_attributes_for :players 
end 

class Player < ActiveRecod::Base 
    belongs_to :team 
end 

und für Backbone-Client, ich habe ein Spieler Modell und einen Spieler Sammlung definiert (nicht dargestellt)

und dann das enthält Team Modell (HINWEIS: nein Teams Sammlung)

Demo.Models.Team = Backbone.Model.extend({ 
    urlRoot: '/teams', 
    defaults: { 
    'team_size': 12 
    }, 
    initialize: function() { 
    this.players = new Demo.Collections.Players()); 
    }, 
    toJSON: function() { 
    var json = _.clone(this.attributes); 
    json.players_attributes = this.players.map(function(player) { 
     return player.toJSON(); 
    }); 
    return json; 
    } 
} 

Wenn ich meine Zeichenfolge JSON im Browser prüfen, alles sieht gut aus:

{"team_size":12, "players_attributes":[{"name":"Fred"},{"name":"Jim" },{"name":"Mark"}]} 

Bei der Überprüfung der Serverprotokolle wird das einzige oberste Attribut ("Teamgröße") einmal auf der obersten Ebene wiederholt und dann unter einem Stammschlüssel wiederholt.

Started POST "/teams" for 127.0.0.1 at 2012-06-07 13:39:40 -0400 
Processing by TeamsController#create as JSON 
    Parameters: { 
    "team_size"=>12, "players_attributes":[{"name":"Fred"},{"name":"Jim" },{"name":"Mark"}]}, 
    "team"=>{"team_size"=>12} 
    } 

Ich habe ein paar Fragen:

  1. Was ist der beste Weg, um das player_attributes verschachtelt sind im Innern des Wurzelschlüssels zu gewährleisten? Ich (damit ich eine verschachtelte Sicherung in TeamController, in der Standard-Rails-Art machen kann: (zB Team.create (params [: team])) kann ich dies mit einigen Javascript-Hackereien innerhalb von jSON erreichen, aber ich vermute, da ist ein einfacher, sauberer Weg.

  2. ist das Standard, erwünschtes Verhalten? Um Duplikate von Attributen wie diese zu schicken? ich denke, kein Schaden da ist, aber es richtig stinkt nicht.

  3. bin ich die uRL nicht definiert,/UrlRoot richtig oder so?

dank

+2

Backbone sendet genau das Ergebnis von toJSON(): 'params.data = JSON.stringify (model.toJSON());', also entweder Ihr Modell enthält solche Attribute oder etwas Seltsames auf dem Server (es gibt eine überflüssige schließende Klammer im Protokoll). Überprüfen Sie den Inhalt der HTTP-Anfrage in Firebug, um herauszufinden, wen Sie dafür verantwortlich machen können. – Yaroslav

+0

Ich hatte das gleiche Problem mit Backbone und Rails für eine Weile ... jetzt muss ich optimieren und das wird unausstehlich ... irgendeine Idee, woher es kommt? – wulftone

+0

Ich denke, es ist erwähnenswert, dass in meinem Fall (und wahrscheinlich auch bei Ihnen) das Backbone anscheinend nicht-duplizierte Informationen sendet. Firebug sagt mir, dass die POST-Anfrage, die an meinen Server geschickt wurde, die korrekten, nicht-duplizierten Informationen enthielt. Irgendwo, bevor es zu den Rubin "Params" kommt, kopiert es einige Sachen ... warum? – wulftone

Antwort

3

1- Sie müssen die toJSON-Methode überschreiben, um den Modellnamen als Stammverzeichnis des JSON-Elements anzugeben, das an den Server gesendet wird.

Da Sie diese Methode bereits verwirren und übersteuern, sehe ich keine Gründe, diesen Weg zu gehen.

2- Dies ist ein sehr merkwürdiges Verhalten, das Sie beschreiben. Versuchen Sie:

class Team < ActiveRecord::Base 
    self.include_root_in_json = false 
end 

Es wird wahrscheinlich Rails doppelte Pars Parsing zu beseitigen. Ein weiterer Vorteil, den Sie daraus ziehen können, ist, dass Rails das Team nicht als Root-Element des generierten JSONs zum Client einbindet.

3- Ihre Definition von urlRoot ist in Ordnung.

+0

Dies scheint zu funktionieren, solange Sie nicht patchen. Wenn Sie '' 'save''' mit' '{patch: true}' '' verwenden, dann bevorzugt die Backbone-Sync-Methode die Änderungen, die geändert wurden, anstatt die toJSON-Methode aufzurufen. –

0

Ich bin hier angekommen, während ich nach dem gleichen Thema gesucht habe. Selbst wenn es eine alte Frage ist, denke ich, dass es sich lohnt, die Antwort zu geben.

Ich fand tatsächlich eine Rails-Einstellung, die diese doppelten Attribute erklären: wrap_parameters

http://apidock.com/rails/v3.2.13/ActionController/ParamsWrapper/ClassMethods/wrap_parameters

Nur stellen Sie es auf ein leeres Array und Schienen nicht versuchen Parameter wickeln von Ihren JSON-Anfragen kommen.

0

Obwohl Sie den ToJSON Hack von anderen erwähnt verwenden können, ist dies eigentlich keine so gute Idee. Zum einen erzeugt sie ein uneinheitliches Ergebnis zwischen sync und save mit {patch: true} (diese Inkonsistenz ist, weil die Synchronisierungsmethode toJSON ruft, wenn Sie nicht patchen, aber toJSON nicht anrufen, wenn Sie Patch-Sets auf true)

Statt Eine bessere Lösung ist die Verwendung einer gepatchten Version von Backbone, die die Synchronisierungsmethode selbst überlastet. Das Backbone-Rails-Juwel führt dies automatisch aus, oder du kannst backbone_rails_sync.js in deine eigene App ziehen. Eine vollständigere Antwort auf diese Frage finden Sie hier: Backbone.js and Rails - How to handle params from Backbone models?

Verwandte Themen