2012-12-28 5 views
7

Ich versuche herauszufinden, wie Sie Daten unter meteor an den Client senden können. Ich habe zwei Benutzertypen und je nach Benutzertyp ihre Schnittstellen auf dem Client (und somit die Daten, die sie benötigen).Wie senden Sie bedingt Daten an den Kunden in Meteor?

Können sagen Benutzer vom Typ sind counselor oder student. Jedes Benutzerdokument hat so etwas wie role: 'counselor' oder role: 'student'.

Studenten haben Schüler spezifische Informationen wie sessionsRemaining und counselor und Berater haben Dinge wie pricePerSession usw.

Wie würde ich sicherstellen, dass Meteor.user() auf der Client-Seite, die Informationen, die ich brauche, und extra keine? Wenn ich als Student angemeldet bin, sollte Meteor.user()sessionsRemaining und counselor enthalten, aber nicht, wenn ich als Berater eingeloggt bin. Ich denke, dass ich nach bedingten Veröffentlichungen und Abonnements in Meteor-Begriffen suche.

+0

ich jetzt ein paar Antworten bekommen habe, und ich bin nicht sicher, ob ich weiß, wie man das Beste holen, weil sie Alle scheinen auf der Oberfläche zu funktionieren. Ich denke, ich hätte gerne die einfachste, "meteorischste" Version, die für noch komplexere Situationen funktioniert (dh wenn Rollen sich nicht gegenseitig ausschließen, etc.) – Diogenes

+0

In diesem Fall solltest du wahrscheinlich @ debergalis 'Antwort wählen, da er einer der Schöpfer ist von Meteor. Nicht viel kometenhafter als das :) – Rahul

Antwort

13

Verwenden Sie die Felder Option, um nur die Felder zurückkehren Sie möchten von einer Mongo-Abfrage.

Meteor.publish("extraUserData", function() { 
    var user = Meteor.users.findOne(this.userId); 
    var fields; 

    if (user && user.role === 'counselor') 
    fields = {pricePerSession: 1}; 
    else if (user && user.role === 'student') 
    fields = {counselor: 1, sessionsRemaining: 1}; 

    // even though we want one object, use `find` to return a *cursor* 
    return Meteor.users.find({_id: this.userId}, {fields: fields}); 
}); 

Und dann auf dem Client rufen Sie einfach

Meteor.subscribe('extraUserData'); 

Abonnements in Meteor überlappen. Das Besondere an diesem Ansatz ist, dass die Veröffentlichungsfunktion, die zusätzliche Felder an den Client sendet, mit der Veröffentlichungsfunktion von Meteor hinter den Kulissen zusammenarbeitet, die grundlegende Felder wie die E-Mail-Adresse und das Profil des Benutzers sendet. Auf dem Client ist das Dokument in der Meteor.users Sammlung die Vereinigung der zwei Gruppen von Feldern.

Meteor.publish("users", function() { 
    //this.userId is available to reference the logged in user 
    //inside publish functions 
    var _role = Meteor.users.findOne({_id: this.userId}).role; 
    switch(_role) { 
     case "counselor": 
      return Meteor.users.find({}, {fields: { sessionRemaining: 0, counselor: 0 }}); 
     default: //student 
      return Meteor.users.find({}, {fields: { counselorSpecific: 0 }}); 
    } 
}); 

Dann in Ihrem Client:

+2

Eine subtile Anmerkung: Wenn sich die Rolle des Benutzers dynamisch ändern kann, merkt dieser Publisher das nicht und ändert die Felder, die er veröffentlicht. Wenn Sie so etwas tun müssen, müssen Sie es jetzt manuell über "beobachten" implementieren; hoffentlich in der Zukunft wird Meteor eine Möglichkeit haben, eine vollständig reaktive Veröffentlichung zu machen. –

+0

Beachten Sie auch, dass, da 'Meteor.user()' sich ändert, sobald 'extraUserData' als bereit markiert ist, alle Autoruns zweimal erneut ausgeführt werden: einmal beim ersten Laden des angemeldeten Benutzers und einmal beim Laden von 'extraUserData'. Um dies zu vermeiden, verwenden Sie stattdessen 'Meteor.userId()': Es wird nur einmal geändert. –

+0

Beachten Sie auch, dass beim Zusammenführen überlappender Datensätze (Cursor) nur die Werte auf der obersten Ebene verglichen werden. Das heißt, wenn eine Subskription '{a: {x: 'x'}}' und eine andere ''{a: {y:' y '}}' '(für Dokumente mit derselben' _id') enthält, dann wird der Client ** nicht ** erhalten Sie {a: {x: 'x', y: 'y'}} 'wie Sie vielleicht erwarten, aber ein beliebiges der Originale. Siehe [dieses offene Problem] (https://github.com/meteor/meteor/issues/3764), besser beschrieben in [diesem geschlossenen Problem] (https://github.com/meteor/meteor/issues/903). – BudgieInWA

3

Meteor Benutzer werden standardmäßig nur mit ihren grundlegenden Informationen veröffentlicht, daher müssen Sie diese Felder manuell dem Client hinzufügen, indem Sie Meteor.publish verwenden. Zum Glück haben die Meteor docs on publish ein Beispiel, das Ihnen zeigt, wie dies tun:

// server: publish the rooms collection, minus secret info. 
Meteor.publish("rooms", function() { 
    return Rooms.find({}, {fields: {secretInfo: 0}}); 
}); 

// ... and publish secret info for rooms where the logged-in user 
// is an admin. If the client subscribes to both streams, the records 
// are merged together into the same documents in the Rooms collection. 
Meteor.publish("adminSecretInfo", function() { 
    return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}}); 
}); 

Grundsätzlich wollen Sie einen Kanal veröffentlichen, die bestimmte Informationen an den Client zurückgibt, wenn eine Bedingung erfüllt ist, und andere Informationen, wenn dies nicht der Fall . Dann abonnierst du diesen Kanal auf dem Client.

In Ihrem Fall möchten Sie wahrscheinlich so etwas wie dies in dem Server:

Meteor.publish("studentInfo", function() { 
    var user = Meteor.users.findOne(this.userId); 

    if (user && user.type === "student") 
    return Users.find({_id: this.userId}, {fields: {sessionsRemaining: 1, counselor: 1}}); 
    else if (user && user.type === "counselor") 
    return Users.find({_id: this.userId}, {fields: {pricePerSession: 1}}); 
}); 

und dann abonnieren auf dem Client:

Meteor.subscribe("studentInfo"); 
+1

Whoops, wir überschnitten uns. Aber "Meteor.user" funktioniert nicht in Veröffentlichungsfunktionen. Siehe die Variante in meiner Antwort. – debergalis

+0

Meine Entschuldigung ist, dass ich // Pseudocode darüber geschrieben habe! Aber du hast recht ;-) – Rahul

+1

Ich vergesse, ich kann nur Sachen bearbeiten. Behoben :) – debergalis

0

Da Meteor.users eine Sammlung wie jede andere Meteor Sammlung ist, können Sie tatsächlich seine propagierten Inhalte wie jede andere Meteor Sammlung verfeinern

Meteor.subscribe("users"); 

Folglich wird Meteor.user() automatisch entsprechend der Rolle des angemeldeten Benutzers abgeschnitten.Hier

ist eine Komplettlösung:

if (Meteor.isServer) { 
    Meteor.publish("users", function() { 
     //this.userId is available to reference the logged in user 
     //inside publish functions 
     var _role = Meteor.users.findOne({ _id: this.userId }).role; 
     console.log("userid: " + this.userId); 
     console.log("getting role: " + _role); 
     switch (_role) { 
      case "counselor": 
       return Meteor.users.find({}, { fields: { sessionRemaining: 0, counselor: 0 } }); 
      default: //student 
       return Meteor.users.find({}, { fields: { counselorSpecific: 0 } }); 
     } 
    }); 

    Accounts.onCreateUser(function (options, user) { 
     //assign the base role 
     user.role = 'counselor' //change to 'student' for student data 

     //student specific 
     user.sessionRemaining = 100; 
     user.counselor = 'Sam Brown'; 

     //counselor specific 
     user.counselorSpecific = { studentsServed: 100 }; 

     return user; 
    }); 
} 

if (Meteor.isClient) { 
    Meteor.subscribe("users"); 

    Template.userDetails.userDump = function() { 
     if (Meteor.user()) { 
      var _val = "USER ROLE IS " + Meteor.user().role + " | counselorSpecific: " + JSON.stringify(Meteor.user().counselorSpecific) + " | sessionRemaining: " + Meteor.user().sessionRemaining + " | counselor: " + Meteor.user().counselor; 
      return _val; 
     } else { 
      return "NOT LOGGED IN"; 
     } 
    }; 
} 

Und die HTML:

<body> 
    <div style="padding:10px;"> 
     {{loginButtons}} 
    </div> 

    {{> home}} 
</body> 

<template name="home"> 
    <h1>User Details</h1> 
    {{> userDetails}} 
</template> 

<template name="userDetails"> 
    DUMP: 
    {{userDump}} 
</template> 
Verwandte Themen