Реализация отношения "многие ко многим" с помощью Backbone-Relational

У меня есть простое приложение, которое определяет два класса, 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, чтобы обернуть коллекцию и преобразовать идентификаторы в ссылки.


person Trevor Elliott    schedule 23.07.2013    source источник


Ответы (2)


В итоге я заставил это работать так, как я хотел. Отношения «многие ко многим» поддерживаются в базе данных, но доступ к этим отношениям в моих моделях Backbone возможен только в одном направлении. Я решил, что модели Person будут автономными, а модели PersonGroup будут иметь набор ссылок на модели Person, с которыми они связаны.

Ключевые моменты, которые заставили все работать, заключались в том, чтобы указать includeInJSON: "ID" и удалить reverseRelation. Это по-прежнему позволяет вам получить доступ к ссылкам на модели в JavaScript, но он правильно сериализуется и десериализуется в JSON. У моделей Person просто нет доступа к свойству навигации для групп, в которых они находятся, однако они могут существовать в нескольких группах нормально.

Я просто предположил, что использование списка идентификаторов потребует перехода через обручи для разрешения ссылок, но Backbone-relational, похоже, использует глобальное хранилище моделей Backbone для разрешения ссылок по идентификатору без создания дублирующих моделей. (например, три разные группы могут ссылаться на одно и то же лицо, и когда-либо создается только одна модель).

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, поэтому отслеживание изменений распространяется на все приложение.

person Trevor Elliott    schedule 23.07.2013

Этому вопросу около двух месяцев, тем не менее, я хотел бы поделиться тем, что я столкнулся с аналогичными проблемами, связанными с отношениями «многие ко многим», при работе с реляционной Backbone. Эти проблемы привели к написанию собственной реализации отношений Backbone, которые поддерживают отношения «многие ко многим» без промежуточной модели связывания: Backbone-JJRelational

Я отвечаю как один из авторов, но, возможно, стоит проверить.
Например, JSON, который вы разместили в своем вопросе, будет автоматически десериализован следующим образом:
Каждая PeopleGroups-модель имеет атрибут People, который является Backbone.Collection, содержащим соответствующие People-модели и (конечно) наоборот, поэтому к отношению можно легко получить доступ с обеих сторон (без модели связывания).
Некоторые концепции Backbone-JJRelational: аналогично Backbone-реляционному (например, глобальное хранилище моделей).

person johnnycrab    schedule 19.09.2013