javascript backbone.js backbone-relational knockback.js

javascript - Implementar una relación de muchos a muchos con Backbone-Relational



backbone.js knockback.js (2)

Tengo una aplicación simple que define dos clases, una Person y un PersonGroup , en donde hay una relación de muchos a muchos. Una Persona no puede tener ningún grupo, ni ser asignada a todos los grupos, ni nada entre ellos.

El ejemplo de backbonerelational.org sugiere usar un modelo intermedio para las relaciones de muchos a muchos, sin embargo, no puedo lograr que este patrón funcione con la extracción (deserialización) y el almacenamiento (serialización).

Lo que quiero hacer es utilizar Backbone para deserializar un JSON similar al siguiente:

{ People: [ { "ID": 1, "Name": "John" }, { "ID": 2, "Name": "Bob" }, { "ID": 3, "Name": "Tim" }, ], PeopleGroups: [ { "ID": 1, "Name": "Owners", "People": [ 1, 2 ], }, { "ID": 2, "Name": "Everyone", "People": [ 1, 2, 3 ], }, ] }

Estoy usando Knockback / Knockout para el enlace de datos, así que el problema es que necesito poder acceder a las relaciones por referencia. Una serie de ID no me sirve de nada, a menos que pueda crear Knockback.CollectionObservable para envolver la colección y resolver los ID a las referencias.


Esta pregunta tiene alrededor de dos meses, sin embargo, me gustaría compartir que me encontré con problemas similares relacionados con las relaciones de muchos a muchos al trabajar con Backbone-relational. Estos problemas llevaron a la escritura de una implementación propia de relaciones Backbone que admiten relaciones de muchos a muchos sin un modelo de vinculación entre: Backbone-JJRelational

Estoy respondiendo como uno de los autores, pero podría valer la pena revisarlo.
El JSON que publicó en su pregunta, por ejemplo, se deserializaría automáticamente de la siguiente manera:
Cada PeopleGroups tiene un atributo People que es un Backbone.Collection que contiene los People mode y, por supuesto, viceversa, por lo que se puede acceder fácilmente a la relación desde ambos lados (sin un modelo de enlace).
Algunos conceptos de Backbone-JJRelational son similares a Backbone-relational (tienda de modelo global, por ejemplo).


Terminé haciendo que esto funcionara como quería. La relación Many-to-Many se mantiene en la base de datos, pero solo se puede acceder a las relaciones en mis modelos Backbone en una dirección. Decidí que los modelos Persona serían independientes y los modelos PersonGroup tendrían una colección de referencias a los modelos Persona a los que están vinculados.

Los puntos clave que hicieron que todo funcionara fueron especificar includeInJSON: "ID" y eliminar la relación reverseRelation . Esto todavía le permite acceder a las referencias a los modelos en JavaScript, pero se serializa y deserializa correctamente a JSON. Los modelos Persona simplemente no tienen acceso a una propiedad de navegación para los Grupos en los que se encuentran, sin embargo, pueden existir en múltiples grupos.

Simplemente asumí que el uso de una lista de ID obligaría a saltar a través de aros para resolver las referencias, pero Backbone-relational parece usar el almacén de modelo Backbone global para resolver las referencias por ID sin crear modelos duplicados. (por ej., tres grupos diferentes pueden hacer referencia a la misma Persona y solo se crea un modelo).

var Person = Backbone.RelationalModel.extend( { idAttribute: "ID", }); var PersonGroup = Backbone.RelationalModel.extend( { idAttribute: "ID", relations: [ { type: Backbone.HasMany, key: "People", relatedModel: "Person", collectionType: "PersonCollection", includeInJSON: "ID", }, ], });

Y aquí está el resto de la plomería si ayuda a alguien. Puede definir Backbone.Collections de la siguiente manera y obtenerlos a través de solicitudes API separadas:

var PersonCollection = Backbone.Collection.extend( { model: Person, url: "/api/person", }); var PersonGroupCollection = Backbone.Collection.extend( { model: PersonGroup, url: "/api/persongroup", }); var PersonModels = new PersonCollection(); var GroupsModels = new PersonGroupCollection(); this.PersonModels.fetch(); this.GroupsModels.fetch(); this.People = kb.collectionObservable( this.PersonModels, { factories: { "models": PersonViewModel, }, } ); this.PersonGroups = kb.collectionObservable( this.GroupsModels, { factories: { "models": PersonGroupViewModel, "models.People.models": PersonViewModel, }, } );

Incluí las colecciones específicas de Knockback.js para usar enlaces de Knockout.js. Solo se crea un ViewModel por modelo, por lo que el seguimiento de cambios se propaga a través de toda la aplicación.