2012-12-28 9 views
7

मैं यह पता लगाने की कोशिश कर रहा हूं कि meteor में ग्राहक को सशर्त रूप से डेटा कैसे भेजना है। मेरे पास दो उपयोगकर्ता प्रकार हैं, और उपयोगकर्ता के प्रकार के आधार पर, क्लाइंट पर उनके इंटरफेस (और इस प्रकार उन्हें आवश्यक डेटा अलग है)।आप मेटीर में क्लाइंट को सशर्त रूप से डेटा कैसे भेजते हैं?

मान लें कि उपयोगकर्ता counselor या student टाइप कर रहे हैं। प्रत्येक उपयोगकर्ता दस्तावेज़ में role: 'counselor' या role: 'student' जैसे कुछ है।

छात्रों

कैसे मुझे यकीन है कि Meteor.user() क्लाइंट पक्ष के बारे में जानकारी की आवश्यकता है, और कोई भी अतिरिक्त है कि बनाना होगा sessionsRemaining और counselor की तरह छात्र विशेष जानकारी है, और सलाहकारों pricePerSession तरह बातें है, आदि? यदि मैं एक छात्र के रूप में लॉग इन हूं, Meteor.user() में sessionsRemaining और counselor शामिल होना चाहिए, लेकिन यदि मैं परामर्शदाता के रूप में लॉग इन नहीं हूं। मुझे लगता है कि मैं जो खोज रहा हूं वह सशर्त प्रकाशन और उल्का शर्तों में सदस्यता है।

+0

मैं अब कुछ जवाब मिल गया है और मुझे यकीन है कि मुझे पता है कि क्योंकि वे सबसे अच्छा लेने के लिए नहीं कर रहा हूँ सब सतह पर काम करने लगते हैं। मुझे लगता है कि मैं सबसे सरल, सबसे 'उल्कापिंड' संस्करण चाहता हूं जो कि और भी जटिल परिस्थितियों के लिए काम करता है (यानी जब भूमिका पारस्परिक रूप से अनन्य नहीं होती है) – Diogenes

+0

उस स्थिति में आपको संभवतः @ डेबर्गिस का जवाब चुनना चाहिए क्योंकि वह रचनाकारों में से एक है उल्का का उस से अधिक उल्का नहीं मिलता :) – Rahul

उत्तर

13

क्षेत्रों के लिए विकल्प का उपयोग केवल क्षेत्रों वापसी आप एक मोंगो क्वेरी से चाहते हैं।

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

और फिर ग्राहक पर सिर्फ फोन

Meteor.subscribe('extraUserData'); 

सदस्यता उल्का में ओवरलैप कर सकते हैं। तो इस दृष्टिकोण के बारे में साफ-सुथरा यह है कि क्लाइंट के लिए अतिरिक्त फ़ील्ड जहाजों का काम करता है जो मेटीर के पीछे के दृश्यों के साथ काम करता है जो मूल फ़ील्ड भेजता है, जैसे कि उपयोगकर्ता का ईमेल पता और प्रोफ़ाइल। ग्राहक पर, Meteor.users संग्रह में दस्तावेज़ फ़ील्ड के दो सेटों का संघ होगा।

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

फिर, अपने ग्राहक में:

+2

एक सूक्ष्म नोट: यदि उपयोगकर्ता की भूमिका गतिशील रूप से बदल सकती है, तो यह प्रकाशक यह ध्यान नहीं देगा कि वह कौन से फ़ील्ड प्रकाशित कर रहा है उसे बदल सकता है। अगर आपको ऐसा कुछ करने की ज़रूरत है, तो आपको वर्तमान में इसे 'निरीक्षण' के शीर्ष पर मैन्युअल रूप से कार्यान्वित करना होगा; उम्मीद है कि भविष्य में मौसम में पूरी तरह से प्रतिक्रियाशील प्रकाशन करने का कोई तरीका होगा। –

+0

यह भी ध्यान दें कि 'अतिरिक्त यूज़रडेटा' को तैयार होने के बाद 'Meteor.user()' बदल जाएगा, सभी Autoruns दो बार फिर से चलाए जाएंगे: एक बार जब लॉग इन उपयोगकर्ता को पहले लोड किया जाता है, और एक बार जब 'अतिरिक्त यूज़रडेटा' लोड हो जाता है। इससे बचने के लिए, 'Meteor.userId() 'का उपयोग करें: यह केवल एक बार बदल जाएगा। –

+0

यह भी ध्यान दें कि ओवरलैपिंग रिकॉर्ड सेट (कर्सर) विलय करते समय, केवल शीर्ष स्तर मानों की तुलना की जाती है। इसका अर्थ यह है कि यदि एक सदस्यता में '{a: {x: 'x'}} है और दूसरे में' {a: {y: 'y'}} 'है (उसी' _id' वाले दस्तावेज़ों के लिए) तो ग्राहक होगा ** नहीं ** '{a: {x: 'x', y: 'y'}} प्राप्त करें जैसा कि आप उम्मीद कर सकते हैं, लेकिन मूल रूप से एक मनमाना। [यह खुला मुद्दा] देखें (https://github.com/meteor/meteor/issues/3764), बेहतर [इस बंद समस्या] में वर्णित है (https://github.com/meteor/meteor/issues/903)। – BudgieInWA

3

डिफ़ॉल्ट रूप से उल्का उपयोगकर्ता केवल अपनी मूलभूत जानकारी के साथ प्रकाशित होते हैं, इसलिए आपको इन क्षेत्रों को मैन्युअल रूप से Meteor.publish का उपयोग करके क्लाइंट में जोड़ना होगा। शुक्र है, Meteor docs on publish एक उदाहरण आप कैसे यह करने के लिए पता चलता है कि है:

// 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}}); 
}); 

मूल रूप से आप जब यह नहीं है एक चैनल है कि ग्राहक के लिए कुछ जानकारी है जब एक की स्थिति उत्पन्न होने और अन्य जानकारी देता है प्रकाशित करना चाहते हैं । फिर आप क्लाइंट पर उस चैनल की सदस्यता लेते हैं।

आपके मामले में, आप शायद सर्वर में कुछ इस तरह हैं:

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

और फिर ग्राहक पर सदस्यता:

Meteor.subscribe("studentInfo"); 
+1

ओह, हमने ओवरलैप किया। लेकिन 'meteor.user' प्रकाशित कार्यों में काम नहीं करता है। मेरे उत्तर में संस्करण देखें। – debergalis

+0

मेरा बहाना यह है कि मैंने इसके ऊपर // छद्म कोड लिखा था! लेकिन आप सही हैं ;-) – Rahul

+1

मैं भूल जाता हूं कि मैं सिर्फ चीजों को संपादित कर सकता हूं। फिक्स्ड :) – debergalis

0

क्योंकि Meteor.users किसी अन्य उल्का संग्रह की तरह एक संग्रह है, आप वास्तव में किसी भी अन्य उल्का संग्रह की तरह अपने प्रचार सामग्री को परिष्कृत कर सकते

Meteor.subscribe("users"); 

नतीजतन, Meteor.user() लॉग-इन उपयोगकर्ता की भूमिका के आधार पर स्वचालित रूप से छोटा कर दिया जाएगा।

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"; 
     } 
    }; 
} 

और एचटीएमएल:

यहाँ एक पूर्ण समाधान है

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

    {{> home}} 
</body> 

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

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