2013-11-27 30 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方法。 –