ОБНОВЛЕНИЕ: Решение находится в нижней части вопроса
У меня есть экспресс-сайт с использованием мангусты.
Я бы очень сильно сказал, что у меня есть взрослые, дети и домашние модели. Когда я создаю методы для детей, я могу вызывать их изнутри для взрослых и получать результаты. Я также могу позвонить им из моих просмотров .ejsОднако, когда я создаю методы на дому, я могу получить результат только из моих представлений .ejs и получить неопределенный при вызове изнутри методов для взрослых. Пример кода следующий.
adult.js
const mongoose = require('mongoose');
const adultSchema = mongoose.Schema({
name: { type: String },
size: {type: String},
kids: [{type: mongoose.Schema.Types.ObjectId, ref: 'Kid', required: true}]
house:{type: mongoose.Schema.Types.ObjectId, ref: 'House', required: true}
});
adultSchema.method({
getKidsDescription: function() {
if (this.kids.length < 1) {
return 'No kids yet';
} else {
let ev = 'Kids, aged: ';
let kds = this.kids;
kds.forEach(function(k){
ev = ev + 'k.getAge()' // works
})
return ev;
}
},
getHouseDescription: function(){
return 'A fabulous house on '+this.house.getFullStreet(); // does not work
}
})
module.exports = mongoose.model('Adult', adultSchema);
kid.js
const mongoose = require('mongoose');
const kidSchema = mongoose.Schema({
name: { type: String },
size: {type: String},
birthdate: {type:Date}
});
kidSchema.method({
getAge: function() {
return (Math.floor(new Date() - this.birthdate)/(1000*60*60*24*365))
},
})
module.exports = mongoose.model('Kid', kidSchema);
house.js
const mongoose = require('mongoose');
const houseSchema = mongoose.Schema({
name: { type: String },
city: {type: String},
street: {type:String}
});
houseSchema.method({
getFullStreet: function() {
return this.street + ' Road';
},
})
module.exports = mongoose.model('House', houseSchema);
Когда я делаю запрос для Adult, это выглядит так:
controller.js
exports.main = async (req, res, next) => {
if (req.theAdult) {
try {
const found = await db.fetchAdult(req.theAdult._id)
res.render('/main', {
//theHouse: found.house //below I show this working
});
} catch(e) {
throw new Error(e.message)
}
} else {
res.redirect('/');
}
}
db.js
exports.fetchAdult = (id) => {
return Adult.findById(id)
.populate({ path: 'kids'})
.populate({ path: 'house'})
.exec()
.then(doc => {
return doc;
});
}
Предполагая, что дом передается для просмотра как объект при визуализации (закомментировано выше), это работает
view.ejs
<p> <%= theHouse.getFullStreet() %></p>
Если предположить, что дом, заполненный при вызове для загрузки Adult, возвращает неопределенное значение.
view.ejs
<p> <%= theAdult.house.getFullStreet() %></p>
В то же время обе эти работы
view.ejs
<ul> <% theAdult.kids.forEach(function(k) { %>
<li><%= k.getAge() %> </li>
<% }); %>
</ul>
<p> <% theAdult.getKidsDescription() %> </p>
Я не понимаю, как работают вызовы методов для объектов в массиве иработать в представлении, но не работать для объектов в массиве. Это ошибка одного ребенка (для меня). Если бы он не работал в представлении, я бы предположил, что метод getFullStreet()
был проблемой, но он работает в представлении. Если бы методы массива не могли быть вызваны в родительском объекте, я бы предположил, что проблема заключалась в попытке доступа к getFullStreet()
в родительском объекте.
Чего мне не хватает?
РЕШЕНИЕ Я получал theAdult
в моем звонке для показа view.ejs, но тогда я действительно полагался на currentAdult
, которыйотносится к req.adult
и не имеет заполненных полей. Мое решение состояло в том, чтобы добавить предварительный хук к схеме для взрослых, которая всегда заполняет дом при поиске.
в adult.js
adultSchema.pre('find', function() {
this.populate('house')
})