2013-11-27 32 views
1

假设如下当前情况:服务器侧无功流星出版

  • 我有一个集“表”
  • 表是具有相似特性的对象{私人:0,PRIVATE1,private2,...} (席0,1,2 ...)
  • 我发布的收集与2个参数,一个TABLEID第二个座位。
  • 考虑到座位上,公布将过滤(隐藏)属性的客户端必须不能看到的。
  • 对于现在的TABLEID和座位是从客户端的会话采取所以一切是被动的。
  • 我有一个“takeSeat(seatNb)”方法。如果一个客户调用这个方法并且被允许在餐桌上就座,那么座位号被发回给客户,然后客户将它放入座位关键下的会话中。因此,这将更新订阅并正确过滤表格的座位内容。

我不满意这个设计,因为我意识到客户端可能是通过订阅自己的座位作弊。另外(更重要的是)我在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}); 
     }); 

如何继续?有没有更好的方法来实现这个目标?

回答

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

你可以看看这个,所以我认为我的问题和你的问题类似,但我不知道如何把它们放在一起? http://stackoverflow.com/q/34479708/271873 –

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

如果用户的座椅变化,则表集合的当前表的文件将更新。

这个例子做了一些假设,也需要调整,如果这些都不是真正适合你:

  • 你可以找到一个给定SEAT_ID(如果你不能,你可能需要存储的表表格ID也在
  • seat_id总是属于同一张表(如果没有,则需要将更改的处理程序添加到存储该信息的任何位置)
  • 返回的表信息通过发布不会改变(如果是这样,您需要添加一个更改的句柄到表集合,类似于用户句柄)
+0

完美,我有你的理念去适应我的情况。我其实已经能够做些更琐碎的事情了,很多谢谢你的线索 –

-1

我有一个类似的问题,写了解决问题的这两个大气包:

https://atmosphere.meteor.com/package/server-deps

https://atmosphere.meteor.com/package/reactive-publish

与陨石安装第二个包,使用“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}}); 
    } 
    } 
}); 
+0

这两个软件包都没有文档,当我尝试添加它们时,服务器开始抱怨缺少onStop方法。 –