【问题标题】:Meteor: collection helpers or transform on FS.Collection?Meteor:收集助手或 FS.Collection 上的转换?
【发布时间】:2016-01-31 09:00:53
【问题描述】:

使用 dburles:collection-helpers 包,您可以在任何 Mongo.collection 上添加集合助手。但我不能在 FS.Collection 上这样做。我得到 TypeError: Object [object Object] has no method 'helpers'。变换功能也不起作用。

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});

【问题讨论】:

  • 在 CollectionFS 文档中,说 可通过 myFSCollection.files 获得的基础 Mongo.Collection 实例 错过了该部分。但仍然出现错误:错误:[Can't apply helpers to 'cfs.photos.filerecord' a transform function already exists!]
  • 我刚刚发现 atmospherejs.com/maximum/multi-transform 可以帮助您将类似帮助程序的转换应用到您的 collectionfs 实例。

标签: meteor meteor-helper collectionfs


【解决方案1】:

好的,我知道这不是我正在寻找的不太容易的解决方案。因为我使用的是发布复合包。我可以只发布带有照片的用户数据(仅限个人资料字段)。在客户端我可以像这样做模板助手:

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}}
  ...

【讨论】:

    【解决方案2】:

    matb33-collection-helpers 包通过将转换函数应用于集合来工作。 CollectionFS 已经应用了自己的转换函数,因此您不能用集合助手包中的函数覆盖它。

    正如issue tracker 所建议的那样

    由于 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/*']
            }
        }
    });
    

    最后,您可以选择存储用户 ID 并发布响应式联接

    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();
      }
    })
    

    【讨论】:

    • 我用我拥有的代码编辑了我的问题,但它不起作用。你如何扩展 FS.File 原型呢?有什么我可以看的例子吗?
    • 我已更新答案以反映您似乎正在寻求的 元数据 解决方案。
    • 抱歉回复晚了我只有有限的时间和使用电脑。您的代码正在插入带有userId 的文件对象作为uploadedBy 元数据。我已经这样做了。但是在 fs 集合中,我试图基于userIdtransform 并获取用户的数据(上传的那个)。喜欢这个fileObj.uploader = Meteor.users.find({_id: fileObj.uploadedBy}); return fileObj;。所以在模板上我可以做uploader.profile.name 来获取用户的名字而不是id。显然我失败了
    • 我添加了自己的答案,它有效。但我真的很想知道艰难的道路,并将进一步研究它。感谢您的帮助。
    • @Zaya 我已经更新了答案,因此我们现在存储名称而不是 userId,或者如果您愿意,可以同时存储两者。
    猜你喜欢
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 2014-06-12
    相关资源
    最近更新 更多