Метеор: сбор помощников или трансформация на 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}}
  ...
Другие вопросы по тегам