假设以下当前案例:
我对这种设计并不满意,因为我意识到客户可能会通过单独订阅座位而作弊。另外(更重要的是)我在c ++中使用另一个DDP客户端,并希望将此逻辑部分保留在服务器端。即一旦我拿到一个座位就不必订阅另一个座位,如果我在桌子上坐下,我希望服务器自己在桌子上显示正确的字段。
经过几次搜索后,我决定为“玩家”添加一个集合,以便我可以轻松地在“桌面”集合中收到通知,将“播放器”添加或删除到表格中。但这只是问题的一半。我必须实际更改发布本身的处理程序,以便过滤器变为被动。这就是我被困住的地方,这里有一些简化的代码来理解这个案例:
Meteor.publish("current-table", function(table_id)
{
var self = this;
var handle = Players.find({"tableID": table_id}).observeChanges(
{
added: function(id)
{
console.log("A player joined the table added");
self.changed("tables", table_id);
},
removed: function(id) {
console.log("A player left the table");
self.changed("tables", table_id);
}
});
self.onStop(function() {
handle.stop();
});
// PUBLISH THE TABLE BUT HIDE SOME FIELDS BEFORE
var player = Players.findOne({"userID": this.userId, "tableID": table_id}) || {"seat": -1};
var seat = player.seat;
var privateFilter = {"private0": false, "private1": false, "private2": false, "private3": false};
delete privateFilter["private" + seat];
return Tables.find(table_id, {fields: privateFilter});
});
如何进行?是否有更优雅的方式来实现这一目标?
答案 0 :(得分:2)
您可以将座位存储在用户的个人资料中。然后,您的出版物将关注用户个人资料的更改并进行适当调整。
例如:
Meteor.publish("current-table", function() {
var self = this;
var getFilteredTableForSeat = function(seat_id) {
// Get the table for the given seat_id, filtering the fields as appropriate
};
var handle = Meteor.users.find({_id: this.userId}).observeChanges({
changed: function (id, fields) {
if(fields.profile)
self.changed("tables", 'current-table', getFilteredTableForSeat(fields.profile.seat_id));
}
});
self.added("tables", 'current-table', getFilteredTableForSeat(Meteor.users.findOne(this.userId).profile.seat_id));
self.ready();
self.onStop(function() {
handle.stop();
});
});
如果用户座位发生变化,那么Tables集合的当前表格文档将会更新。
这个例子做了一些假设,如果不适合你,则需要调整:
答案 1 :(得分:1)
感谢jrullmann的回答,我决定使用2个集合的反应性制作自定义过滤出版物。这是我的最终代码:
Meteor.publish("current-table", function(table_id)
{
var self = this;
function getFilteredTable()
{
var player = Players.findOne({"userID": self.userId, "tableID": table_id}) || {"seat": -1};
var seat = player.seat;
var privateFilter = {"prv": false, "prv0": false, "prv1": false, "prv2": false, "prv3": false};
delete privateFilter["prv" + seat];
return Tables.findOne(table_id, {fields: privateFilter});
}
var tableHandler = Tables.find(table_id).observeChanges(
{
added: function()
{
self.added('tables', table_id, getFilteredTable());
},
removed: function()
{
self.removed('tables', table_id);
},
changed: function()
{
self.changed('tables', table_id, getFilteredTable());
}
});
self.ready();
self.onStop(function() {
tableHandler.stop();
});
var handle = Players.find({"tableID": table_id}).observeChanges(
{
added: function(collection, id, fields)
{
self.changed('tables', table_id, getFilteredTable());
console.log("added");
},
removed: function(collection, id, fields)
{
// Little trick to avoid meteor use the former deleted (hidden) properties
self.removed('tables', table_id);
self.added('tables', table_id, getFilteredTable());
console.log("removed");
}
});
self.onStop(function() {
handle.stop();
});
});
答案 2 :(得分:-1)
我遇到了类似的问题并编写了这两个解决问题的气氛包:
https://atmosphere.meteor.com/package/server-deps
https://atmosphere.meteor.com/package/reactive-publish
使用meteorite安装第二个包,使用“Meteor.reactivePublish”而不是“Meteor.publish”,当选项{“reactive”:true}的任何查询结果发生变化时,它将自动更新。
自述文件中的这个示例将精确发布用户团队可以看到的项目,并在用户更改团队或团队的可见项目发生更改时更新。
Meteor.reactivePublish(null, function() {
if (this.userId) {
var user = Meteor.users.findOne({_id: this.userId}, {reactive: true});
if (user.team) {
var team = Collections.teams.findOne({_id: user.team}, {reactive: true});
var visibleItems = _.compact(team.visibleItems);
return Collections.items.find({_id: {$in: visibleItems}});
}
}
});