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 заполняет вложенные ассоциации