Backbone.js и встроенные ассоциации «один ко многим» - PullRequest
6 голосов
/ 12 февраля 2012

Макет приложения

Я создаю приложение, в котором можно создавать опросы. Каждый опрос имеет несколько вопросов. Я включаю вопросы в модель опроса (с embeds_many в Mongoid), поэтому опрос может выглядеть следующим образом:

{
  "id":    "4f300a68115eed1ddf000004",
  "title": "Example Survey",
  "questions": 
  [
    {
      "id":      "4f300a68115eed1ddf00000a",
      "title":   "Please describe your experience with backbone.js", 
      "type":    "textarea"
    },
    {
      "title":   "Do you like it?", 
      "id":      "4f300a68115eed1ddf00000b",
      "type":    "radiobutton",
      "options": ["Yes", "Yes, a lot!"]
    }
  ]
}

Теперь есть также редактор опроса, который состоит из SurveyView, который отображает опрос и перечисляет вопросы. Если я нажму на один вопрос, появится QuestionView, где я могу отредактировать вопрос. И когда я удовлетворюсь опросом и нажму кнопку Сохранить, SurveyModel будет отправлено на сервер.

проблема

Каков наилучший способ обработки встроенной ассоциации?

Если я передам survey.get("questions")[any_index] в QuestionView, и вопрос будет изменен, я должен вручную найти question.id в моей модели и обновить свою модель. Это неправильно.

Если я создам QuestionsCollection в моем SurveyModel (это вообще возможно?). Затем я могу сделать что-то вроде извлечения Question из этой коллекции по id, передать его в представление, и когда я изменю модель, все будет обновлено автоматически, но я должен указать url в коллекции, и Backbone будет отправлять отдельные вопросы на сервер, если что-то обновляется.

Любое предложение о том, как сделать это магистральным способом?

Ответы [ 4 ]

15 голосов
/ 12 февраля 2012

Способ создания встроенных связей один-ко-многим в backbone.js

Я реализовал ответ от @Sander и просто хотел опубликовать код:

class Survey extends Backbone.Model

  # Handles the Survey.questions association to parse stuff from the server
  parse: (resp) ->
    if @attributes?.questions?
      @attributes.questions.reset(resp.questions)
    else
      resp.questions = new QuestionsCollection(resp.questions)
    resp

  # Recollects Survey.questions
  toJSON: ->
    attributes = _.clone(@attributes)
    attributes.questions = attributes.questions.toJSON()
    attributes

Тогда я могу сделать что-то вроде:

survey = Survey.get("my-id")
survey.questions.at(0).title = "First question"
survey.questions.at(1).title = "Second question"
survey.save()

Который работает довольно удобно.

5 голосов
/ 12 февраля 2012

вы, безусловно, можете иметь коллекцию вопросов внутри вашей SurveyModel.

но вы правы в том, что вопрос рассматривается как отдельный вопрос (поскольку у каждого вопроса должен быть свой идентификатор, на сервере все же можно узнать, какому опросу он принадлежит ...)

тогда есть разбор вашего json: если вы создаете свою коллекцию и модели вручную, у вас не будет этой проблемы, но если вы добавите вложенный JSON, он не будет автоматически создавать вложенную коллекцию для вашей модели. вам нужно будет указать такие вещи в переопределенном методе разбора.

4 голосов
/ 13 февраля 2012

Я думаю, что вы даже можете сделать это при строительстве

class Survey  extends Backbone.Model

initialize: ->
    @questions = new QuestionsCollection(@get('questions'))

Также вы можете расширить модель для получения вложенных данных:

_.extend Backbone.Model::, deepToJSON: ->
  obj = @toJSON()
  _.each _.keys(obj), (key) ->
    obj[key] = obj[key].deepToJSON()  if _.isFunction(obj[key].deepToJSON)

  obj

_.extend Backbone.Collection::, deepToJSON: ->
  @map (model) ->
    model.deepToJSON()
0 голосов
/ 27 июня 2012

Переопределение parse / toJSON является работоспособным решением.Однако следует помнить, что «this» в методе parse не является объектом модели, когда объект выбирается из коллекции.Затем происходит то, что parse вызывается и результат передается для инициализации.Причина, по которой вам может понадобиться «this» для указания на объект модели, заключается в том, что вы хотите связать события в коллекции.Альтернативный подход заключается в переопределении метода set.Я установил простой скрипт на Github , который демонстрирует этот подход.

...