Angularjs: многие ко многим со сквозными отношениями

В моем приложении есть студенты, которые могут записаться на занятия.

Регистрация записывает даты начала и окончания вместе со ссылкой на какой класс.

Класс имеет такие детали, как имя класса и описание.

Студент (1) - (N) Зачисление (1) - (1) Класс

Следовательно

Студент (1) - (N) класс

Это то, что я хотел бы, чтобы объект выглядел.

{
  "studentId": 1,
  "name": "Henrietta",
  "enrolledClasses": [
    {
      "enrollmentId": 12,
      "startDate": "2015-08-06T17:43:14.000Z",
      "endDate": null,
      "class": 
        { 
          "classId": 15,
          "name": "Algebra",
          "description": "..."
        }
    },
      "enrollmentId": 13,
      "startDate": "2015-08-06T17:44:14.000Z",
      "endDate": null,
      "class": 
        {
          "classId": 29,
          "name": "Physics",
          "description": "..."
        }
    }
}

Но мой RESTful API не может (легко) вывести полную вложенную структуру отношений, потому что ORM не может делать отношения "многие ко многим" со сквозными связями. Таким образом, я получаю ученика и его несколько зачислений, но только ссылку на класс для каждого, а не детали. И мне нужно показать детали, а не просто идентификатор.

Я мог бы подождать, пока объект студента будет доступен, а затем использовать ссылки, чтобы сделать дополнительные вызовы API для каждого classId, чтобы получить подробности, но я не уверен, как, или даже если, затем интегрировать его с объектом студента.

Это то, что я до сих пор.

function findOne() {
  vm.student = StudentsResource.get({
    studentId: $stateParams.studentId
  });
};

Это то, что я получаю от моего API

{
  "studentId": 1,
  "name": "Henrietta",
  "enrolledClasses": [
    {
      "enrollmentId": 12,
      "startDate": "2015-08-06T17:43:14.000Z",
      "endDate": null,
      "class": 15
    },
      "enrollmentId": 13,
      "startDate": "2015-08-06T17:44:14.000Z",
      "endDate": null,
      "class": 29
    }
}

И для деталей класса я могу их по одному, но не понял, как ждать, пока объект ученика не станет доступен, чтобы протолкнуть их в него. Ни как правильно их подтолкнуть...

{ 
  "classId": 15,
  "name": "Algebra",
  "description": "..."
}

{
  "classId": 29,
  "name": "Physics",
  "description": "..."
}

Вопрос

Является ли хорошей практикой объединение данных об ученике и классе (ах) в зачислении в один объект?

  • Если так, какой самый ясный способ пойти об этом?
  • Если нет, то каков еще один эффективный подход?

Имейте в виду, что приложение позволит вносить изменения в сведения об ученике и зачислениях, но не должно позволять вносить изменения в сведения об имени или описании класса. Таким образом, если Angular отправит PUT для объекта, он не должен пытаться отправить детали какого-либо класса, только ссылку. Это будет принудительно применено на стороне сервера для защиты данных, но во избежание ошибок клиент не должен пытаться это сделать.

Для фона я использую SailsJS и PostgreSQL для бэкэнд-API.

1 ответ

Решение

Поэтому, в основном, на стороне Sailsjs вы должны переопределить функцию findOne в вашем StudentController.js. Это предполагает, что вы используете чертежи.

// StudentController.js
module.exports = {
  findOne: function(req, res) {
    Student.findOne(req.param('id')).populate('enrollments').then(function(student){
      var studentClasses = Class.find({
        id: _.pluck(student.enrollments, 'class')
      }).then(function (classes) {
        return classes
      })
      return [student, classes]
    }).spread(function(student, classes){
      var classes = _.indexBy(classes, 'id')
      student.enrollments = _.map(student.enrollments, function(enrollment){
        enrollment.class = classes[enrollment.class]
        return enrollment
      })
      res.json(200, student)
    }).catch(function(err){
      if (err) return res.serverError(err)
    })
  }
}

// Student.js

module.exports = { 
  attributes: {
    enrollments: {
      collection: 'enrollment',
      via: 'student'
    } 
    // Rest of the attributes..   
  }
}

// Enrollment.js

module.exports = {
  attributes: {
    student: {
      model: 'student'
    }
    class: {
      model: 'class'
    }
    // Rest of the attributes...
  }
}

// Class.js

module.exports: {
  attributes: {
    enrollments: {
      collection: 'enrollment',
      via: 'class'
    }
    // Rest of the attrubutes
  }
}

Объяснение:
1. Функция _.pluck, использующая Lo-dash, возвращает массив classIds, и мы находим все классы, которые мы хотели заполнить. Затем мы используем цепочку обещаний.spread(), создаем массив с индексом classid и сопоставляем classIds с фактическими экземплярами классов, которые мы хотели заполнить в зачислениях на студента, возвращенного из Student.findOne ().
2. Верните ученика с зачисленными в него учениками с соответствующим классом.

источник: Sails.js заполняет вложенные ассоциации

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