Внедрение отношений "многие ко многим" с опорными отношениями
У меня есть простое приложение, которое определяет два класса, Person
и PersonGroup
, где существует отношение "многие ко многим". Человек может не иметь группы или быть назначенным на все группы, и все что между ними.
Пример на backbonerelational.org предлагает использовать промежуточную модель для отношений "многие ко многим", однако я не могу заставить этот шаблон работать с извлечением (десериализацией) и сохранением (сериализацией).
Я хочу использовать Backbone для десериализации JSON, подобного следующему:
{
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
],
},
]
}
Я использую Knockback/Knockout для привязки данных, поэтому проблема в том, что мне нужно иметь доступ к отношениям по ссылке. Массив идентификаторов не приносит мне никакой пользы, если только я не могу создать Knockback.CollectionObservable, чтобы обернуть коллекцию и преобразовать идентификаторы в ссылки.
2 ответа
Я закончил тем, что заставил это работать так, как я хотел. Отношение "многие ко многим" сохраняется в базе данных, но к этим отношениям можно получить доступ только в моих моделях магистрали в одном направлении. Я решил, что модели Person будут автономными, а модели PersonGroup будут иметь коллекцию ссылок на модели Person, с которыми они связаны.
Ключевые моменты здесь, которые заставили все работать, должны были указать includeInJSON: "ID"
и удалить reverseRelation
, Это по-прежнему позволяет получить доступ к ссылкам на модели в JavaScript, но корректно сериализует и десериализует в JSON. Модели Person просто не имеют доступа к свойству навигации в группах, в которых они находятся, однако они могут прекрасно существовать в нескольких группах.
Я просто предполагал, что использование списка идентификаторов потребует перехода через обручи для разрешения ссылок, но Backbone-реляционный, похоже, использует глобальное хранилище моделей Backbone для разрешения ссылок по ID без создания дублирующих моделей. (Например, три разные группы могут ссылаться на одного и того же человека, и когда-либо создается только одна модель).
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",
},
],
});
А вот и остальная часть сантехники, если это кому-нибудь поможет. Вы можете определить Backbone.Collections следующим образом и получить их через отдельные запросы API:
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,
},
}
);
Я включил специальные коллекции Knockback.js для использования привязок Knockout.js. Для каждой модели создается только одна модель ViewModel, поэтому отслеживание изменений распространяется по всему приложению.
Этому вопросу уже около двух месяцев, но я хотел бы поделиться с вами тем, что столкнулся с похожими проблемами, связанными со взаимоотношениями "многие ко многим" при работе с Backbone-реляционными. Эти проблемы привели к написанию собственной реализации отношений Backbone, которые поддерживают отношения "многие ко многим" без промежуточной модели: Backbone-JJRelational
Я отвечаю как один из авторов, но, возможно, стоит проверить.
Например, JSON, который вы разместили в своем вопросе, будет автоматически десериализован следующим образом:
каждый PeopleGroups
-модель имеет атрибут People
которая представляет собой коллекцию Backbone.Collection, содержащую People
-модели и (конечно) наоборот, так что отношение может быть легко доступно с обеих сторон (без модели связывания).
Некоторые концепции Backbone-JJRelational аналогичны Backbone-реляционным (например, глобальное хранилище моделей).