希望我的第一个问题不是一个愚蠢的问题。 让我们说我们想与meteor一起构建一个聊天应用程序,包括logedin和匿名用户。聊天应该像这样填写:
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中有没有办法?
感谢您的任何见解或建议
答案 0 :(得分: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();
});
通过这个我终于能够动态覆盖值。
答案 1 :(得分:0)
可悲的是,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});
});
客户端/路由器端:
然后,订阅这两个:这将做什么只包括帖子的userId,只有当它是自己用户的id时。如果没有,它将是未定义的。
然后,我们仍然需要识别案例"匿名发布" vs"由用户发布"。为此,您可以在创建帖子期间添加其他字段,例如is_anonymous
,然后根据用户是否登录的情况设置为true
或false
。然后检查将是:
if (userId) {
status = "Your_Post";
} else if (is_anonymous === false) {
status = "another_logedin_user";
} else {
status = "an_anonymous_user";
}
此解决方案应该有效。我知道,这是可悲的要来这种方式。它使Meteor看起来很笨重而且不切实际的任务应该很容易。这样一个很酷的框架真是太遗憾了!
答案 2 :(得分:0)
您似乎需要在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}}
当然,您也可以使用模板助手来获得相同的结果,但转换更容易在您的应用程序中重复使用。