【问题标题】:Change publicated collection fields value更改发布的集合字段值
【发布时间】:2014-07-25 22:45:44
【问题描述】:

希望我在这里的第一个问题不是愚蠢的。 假设我们想用流星构建一个聊天应用程序,有登录用户和匿名用户。聊天应该这样填写:

var post = {
   userId: user._id,                 // is empty if anonymous user
   submitted: new Date().getTime(),
   text: chat_message
   });

var postId = Posts.insert(post);

发布可能看起来像这样,以确保 userId 没有被转移

Meteor.publish('getTheChat', function() {
  return Post.find({}, {fields: {userId: false});
});

但是有没有办法在返回的集合中动态添加一个字段? 不应发布 userId,而应发布类似 "Your_Post""another_logedin_user""an_anonymous_user" 的状态。有了它,我可以包含一些 CSS,所以聊天看起来有点像 WhatsApp 或 iMessage。

发布方法内部的逻辑可能类似于

if (userId == this.userId) {
   status = "Your_Post";
} else if (userId != null) {
   status = "another_logedin_user";
} else {
   status = "an_anonymous_user";
}

你看,当不同用户调用时,发布应该包含不同的值。 Meteor.publish 有办法吗?

感谢您的任何见解或建议

【问题讨论】:

    标签: meteor


    【解决方案1】:

    感谢两位的想法!但是由于我必须找出(只是为了我内心的平静)如何在发布方法服务器端内部实现,我在 David 的链接的帮助下来到了这个解决方案 - 也许它以后会对某人有所帮助:

    Meteor.publish('getTheChat', function(postId) {
      var currentUserId = this.userId;
      var ownerUserId = Posts.findOne({'_id':postId}).userId;
      var findOptions = {};   // in my final coding these differ for 'chat room owners' and 'normal users'
    
      var transform = function(post) {
        if (currentUserId && post.userId == currentUserId) {
          post.userId = "posted by you";    
        } else if (post.userId == null) {
          post.userId = "anonym posted";
        } else if (post.userId == ownerUserId) {
          post.userId = "posted by owner";
        } else {
          post.userID = "posted by another loged in";
    
        return post;
      }; 
    
      var self = this;
    
      var handle = Posts.find(findOptions).observe({
        added: function (document) {
          self.added('posts', document._id, transform(document));
        },
        changed: function (newDocument, oldDocument) {
          self.changed('posts', document._id, transform(newDocument));
        },
        removed: function (oldDocument) {
          self.removed('posts', oldDocument._id);
        }
      });
    
      self.ready();
    
      self.onStop(function(){
        handle.stop();
      });
    

    有了这个,我终于能够动态地覆盖值。

    【讨论】:

      【解决方案2】:

      您似乎需要在您的 Posts 集合上添加一个转换。您可以在您的发布函数 (as seen here) 中执行此操作,但服务器端转换的计算效率低且难以编写。尽管在只有服务器可以执行操作的情况下它们是必要的 - 例如签名的 URL。在您的情况下,我建议使用标准集合转换,它是在获取文档后应用的过滤器。

      不幸的是,这种转换需要客户端上的userId。我从未见过仅发布 id 就可能导致安全问题的案例。如果您认为您的应用程序就是这种情况,我很想知道为什么。如果您可以克服此限制,请继续阅读...

      您可以在collections 上的文档中阅读有关转换的信息,您可以在evented mind 上查看示例。我个人喜欢为此使用collection-helpers 包。

      如果您尝试收集助手,您的转换可能如下所示:

      Posts.helpers({
        status: function() {
          if (this.userId === Meteor.userId()) {
            return 'Your_Post';
          } else if (this.userId != null) {
            return 'another_logedin_user';
          } else {
            return 'an_anonymous_user';
          }
        }
      });
      

      然后你可以在你的模板中使用它:

      {{#each posts}}
        <p>{{text}} - <span class='status'>{{status}}</span></p>
      {{/each}}
      

      当然,您也可以使用模板助手来实现相同的结果,但转换更容易在您的应用程序中重用。

      【讨论】:

      • 我实际上对你的收集助手解决方案非常感兴趣,但我很怀疑......在包的自述文件中明确指出:“建议设置助手以在服务器和服务器上运行客户端。这样你的助手可以在服务器端和客户端访问。我得出的结论是,要像您的示例一样在模板中访问,必须在客户端定义助手,因此也必须定义每个帖子的 userId ......但关键是要保持该属性对客户。我错过了什么吗?
      • 糟糕,我的错,你说以前不可能。
      【解决方案3】:

      很遗憾,this has been a huge issue for me too,我很遗憾地说,在发布者的查询中添加一个字段并在您的视图中方便地使用它在技术上是不可能的。但是,我有一个可能对你有用的解决方案。只要您想在 Meteor 中保留一些反应性数据,它还会让您了解它会变得多么复杂。

      服务器端:

      首先,创建两个不同的发布者:一个用于当前用户的帖子,一个用于所有其他发布者:

      Meteor.publish('getTheOthersChat', function() {
        return Post.find({$ne:{userId: this.userId}}, {fields: {userId: false});
      });
      
      Meteor.publish('getTheOwnChat', function() {
        return Post.find({userId: this.userId});
      });
      

      客户端/路由器端:

      然后,订阅这两个:这将只在帖子的用户 ID 是自己的用户 ID 时才包含帖子的用户 ID。如果没有,它将是未定义的。

      然后,我们仍然需要区分“匿名发布”与“用户发布”的案例。为此,您可以在帖子创建期间添加另一个字段,例如is_anonymous,然后根据用户是否登录的情况将其设置为truefalse。然后检查将是:

      if (userId) {
         status = "Your_Post";
      } else if (is_anonymous === false) {
         status = "another_logedin_user";
      } else {
         status = "an_anonymous_user";
      }
      

      此解决方案应该有效。我知道,不得不采取这种手段是很可悲的。它使 Meteor 看起来笨重且不切实际,对于应该很容易的任务。这么酷的框架真是太可惜了!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-08
        • 2020-07-03
        • 1970-01-01
        • 2017-02-22
        • 1970-01-01
        相关资源
        最近更新 更多