Внедрение отношений "многие ко многим" с опорными отношениями

У меня есть простое приложение, которое определяет два класса, 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-реляционным (например, глобальное хранилище моделей).

Другие вопросы по тегам