Метеор: сбор помощников или трансформация на FS.Collection?
С пакетом dburles:collection-helpers вы можете добавить помощников коллекции в любой Mongo.collection. Но я не могу сделать это на FS.Collection. Я получаю TypeError: Object [object Object] не имеет метода "помощников". Функция преобразования тоже не работает.
var createUploader = function(fileObj, readStream, writeStream) {
fileObj.uploadedBy = Meteor.users.find({_id: fileObj.uploader});
readStream.pipe(writeStream);
};
Photos = new FS.Collection("photos", {
stores: [
new FS.Store.GridFS("photos", {transformWrite: createUploader})
],
filter: {
allow: {
contentTypes: ['image/*']
}
}
});
Не можете сделать это? Обратите внимание, когда фотография вставлена с клиента FS.File
получает userId
отсюда fileObj.uploadedBy = Meteor.users.find({_id: fileObj.uploader});
2 ответа
Пакет matb33-collection-helpers работает, применяя функцию преобразования к коллекции. У CollectionFS уже есть своя собственная функция преобразования, поэтому вы не можете перезаписать ее функциями из пакета помощников по сбору.
Как предложено в трекере проблем
Поскольку CFS уже применяет преобразование, было бы неплохо использовать помощников по сбору. Вы должны быть в состоянии сделать почти то же самое, расширив прототип FS.File своими собственными функциями.
Вы можете определить пользовательские функции на прототипе. Прототип будет иметь доступ к другим свойствам документа через this
таким образом, у вас была бы та же функциональность с помощниками по сбору.
Другим вариантом будет сохранение информации, связанной с файлом, для отдельного файлового объекта во время вставки в виде метаданных, таких как:
Template.photoUploadForm.events({
'change .photoInput': function(event, template) {
FS.Utility.eachFile(event, function(file) {
var newPhoto = new FS.File(file);
newPhoto.metadata = {uploadedBy: Meteor.user().profile.name};
Photos.insert(newPhoto, function (err, fileObj) {
if (!err) console.log(fileObj._id + " inserted!")
});
});
}
});
Ваш код также может быть переписан для реализации beforeWrite
фильтр вместо transformWrite как в
Photos = new FS.Collection("photos", {
stores: [
new FS.Store.GridFS("photos", {
beforeWrite: function (fileObj) {
fileObj.metadata = {uploadedBy: Meteor.user().profile.name};
}
})
],
filter: {
allow: {
contentTypes: ['image/*']
}
}
});
Наконец, вы можете сохранить идентификатор пользователя и опубликовать реактивное соединение.
Photos = new FS.Collection("photos", {
stores: [
new FS.Store.GridFS("photos", {
beforeWrite: function (fileObj) {
fileObj.metadata = {
uploadedBy: Meteor.userId()
};
}
})
],
filter: {
allow: {
contentTypes: ['image/*']
}
}
});
А для публикации вы можете использовать reywood:publish-composite
Meteor.publishComposite('photosWithUsers', function() {
return {
find: function() {
return Photos.find();
},
children: [
{
find: function(photo) {
return Meteor.users.find(photo.uploadedBy, {
fields: {username: 1, 'profile.name': 1}
});
}
}
]
};
});
Конечно на клиенте нужно подписаться на photosWithUsers
издание.
Теперь для доступа к этой информации в клиенте, поскольку вы не можете применить преобразование или помощник к документам collectionFS, вы можете создать глобальный помощник шаблонов:
Template.registerHelper('getUsername', function(userId) {
check(userId, String);
var user = Meteor.users.findOne(userId);
return user && user.profile.name + ' (' + user.username + ')';
});
Теперь вы можете использовать этот помощник в своих шаблонах:
<template name="somePhoto">
{{#with FS.GetFile "Photos" photo}}
<img src="{{url}}" alt="This photo has been uploaded by {{getUsername uploadedBy}}">
{{/with}}
</template>
Template.somePhoto.helpers({
photo: function() {
return Photos.findOne();
}
})
Хорошо, я знаю, что это не очень простое решение, которое я искал. Так как я использую Publish-композитный пакет. Я могу просто публиковать данные пользователей (только поле профиля) с фотографиями. И на клиенте я могу сделать шаблон помощника следующим образом:
Template.photo.helpers({
photoUploader: function() {
var currentPhoto = Photos.findOne();
var user = Meteor.users.findOne({_id: currentPhoto.uploader});
return user.profile.name;
},
});
а также
<template name="photos">
{{#each photos}}
{{> photo}}
{{/each}}
...
затем
<template name="photo">
{{photoUploader}}
...