Структурирование отношения "многие-ко-многим" между моделями Rails и Backbone.js

Я пытаюсь настроить модель item и модель tag, которые имеют отношение "многие ко многим" (элементы имеют несколько тегов и тегов, принадлежащих нескольким элементам). Я использую Rails и Backbone.js, поэтому мне нужно, чтобы они сохраняли, извлекали и обновляли модели легко друг с другом. Мне также понравилось бы, если бы я мог сохранить новый список тегов для определенного элемента за один раз от клиента.

Каков правильный способ структурирования моделей и контроллеров на стороне Rails и моделей на стороне Backbone, чтобы поддерживать систему RESTful и упростить разделение моделей между ними? В частности, что бы выглядел API на сервере, и каково было бы представление JSON моделей в сохранении и извлечении их?

Я бы очень признателен за любые советы по структуре, и мне не нужны какие-либо детали кода или реализации - просто настройка на высоком уровне будет отличной. Спасибо!

Ответы

Ответ 1

[В дополнение к ответу Папы:]

Для справки, ответ Rails (из Создание нескольких ресурсов в одном RESTful POST в рельсах) заключается в использовании accepts_nested_attributes_for:

class Item < ActiveRecord::Base
  has_many_and_belongs_to :tags
  accepts_nested_attributes_for :tags
end

class Tag < ActiveRecord::Base
  has_many_and_belongs_to :items
end

Далее предполагается, что вы добавили ActiveRecord::Base.include_root_in_json = false к одному из ваших инициализаторов (см. здесь для чего).

Чтобы сохранить список тегов для элемента из Backbone, ответ (из Сохранение вложенных объектов с Rails, backbone.js и accepts_nested_attributes_for) заключается в переопределении sync по модели Item:

sync: (method, model, options) ->
    data = JSON.stringify model.toJSON()
    if (method == "create" || method == "update")
        json = model.attributes
        json = _.extend json, {tags_attributes: model.tags.toJSON()}
        data = JSON.stringify json

    options.data = data
    options.contentType = 'application/json'
    Backbone.sync method, model, options

Это решение может потребовать немного большего количества хакеров, чтобы получить Rails для понимания Backbone, но именно так вы можете начать их настройку.

Ответ 2

Похоже, вы нашли, что ваши рельсы отвечают. Может быть, я могу помочь с основной стороны:

Backbone имеет 2 модели: модель и коллекцию (коллекция, которая просто является списком моделей). Формального описания отношений с позвоночником (афайк) нет, поэтому вам нужно сделать это самостоятельно. Я думаю, что я бы сделал, чтобы справиться с этой структурой, было бы 3 коллекции:

ItemCollection

В коллекции элементов будут храниться все ваши элементы, и каждый элемент будет, в свою очередь, иметь собственный TagCollection, который содержит связанные с ним модели тегов.

ItemCollection.TagCollection

Удерживает ссылки на основной экземпляр TagCollection, но является локальным списком только для этого элемента. Так как вы можете '.add' создать модель для коллекции, то вы можете иметь несколько коллекций с теми же моделями, которые их заполняют.

TagCollection

В TagCollection хранятся теги. Это "основной" список тегов, которые будут ссылаться на каждый элемент ItemCollections TagCollection.

Например: у вас есть 3 тега в вашем TagCollection и 2 элемента.

  • item_1.TagCollection имеет tag_A и tag_B
  • item_2.TagCollection имеет tag_A и tag_C

Если в элементе item_1 добавлен tag_C, вы просто: item_1.TagCollection.add(tag_C) Аналогично, удаление: item_1.TagCollection.remove(tag_C) удалит его из коллекции item_1, но не другие.

Независимо от методов, которые вы используете, вам нужно написать код, чтобы он делал массовые обновления/создает. Помните, что магистраль просто передает список атрибутов вдоль строки JSON в теле запроса, когда он выполняет синхронизацию. Ему все равно, что он отправляет. Итак, пока ваш контроллер был настроен на прием списка (1 или более) на нем, создайте метод, вы должны сделать это довольно просто, выполнив TagCollection.create([список тегов]). Трудная часть будет заключаться в том, чтобы переопределить основную синхронизацию для обработки успешного создания и превратить [список тегов] в отдельные модели для коллекции.

Надеюсь, что это поможет!