2012-04-03 14 views
8

मैं एक DS.Store जो DS.RESTAdapter और एक ChatMessage वस्तु ऐसी के रूप में परिभाषित का उपयोग करता है:परिणाम एंबर-डेटा से फ़िल्टर करने के लिए आइटम जोड़ने

App.ChatMessage = DS.Model.extend({ 
    contents: DS.attr('string'), 
    roomId: DS.attr('string') 
}); 

ध्यान दें कि एक चैट संदेश एक कमरे (सादगी के लिए नहीं दिखाया गया है) में मौजूद है

loadMessages: function(){ 
    var room_id = App.getPath("current_room.id"); 
    this.set("content", App.store.find(App.ChatMessage, {room_id: room_id}); 
} 

यह एक DS.AdapterPopulatedModelArray को content सेट:, मेरे चैट संदेशों नियंत्रक (जो Ember.ArrayController फैली) में तो मैं केवल कमरे के लिए संदेशों को लोड करना चाहते हैं उपयोगकर्ता में है और मेरा विचार खुशी से सभी लौटे हुए चैट संदेशों को {{#each}} ब्लॉक में प्रदर्शित करता है।

postMessage: function(contents) { 
    var room_id = App.getPath("current_room.id"); 
    App.store.createRecord(App.ChatMessage, { 
     contents: contents, 
     room_id: room_id 
    }); 

    App.store.commit(); 
} 

इस सर्वर पर संदेश को बचाने के लिए एक ajax अनुरोध शुरुआत करता है, सब अच्छा अब तक, लेकिन यह नहीं करता है:

अब यह, मैं एक ही नियंत्रक में निम्नलिखित है नया संदेश जोड़ने की बात आती है दृश्य को अपडेट नहीं करें। यह बहुत अधिक समझ में आता है क्योंकि यह एक फ़िल्टर किया गया परिणाम है और यदि मैं App.store.find पर रूम_आईडी फ़िल्टर हटा देता हूं तो यह अपेक्षित के रूप में अपडेट होता है।

this.pushObject(message)App.store.createRecord से लौटा संदेश संदेश के साथ एक त्रुटि उठाता है।

मैं परिणामों को मैन्युअल रूप से आइटम कैसे जोड़ूं? जहां तक ​​मैं कह सकता हूं कि DS.AdapterPopulatedModelArray और DS.FilteredModelArray दोनों अपरिवर्तनीय हैं, ऐसा कोई प्रतीत नहीं होता है।

उत्तर

0

स्रोत का मेरा पठन (DS.Store.find) दिखाता है कि आप वास्तव में इस उदाहरण में जो प्राप्त कर रहे हैं वह एडाप्टरपोप्लेटेड मॉडेलएरे है। जब आप रिकॉर्ड बनाते हैं तो एक फ़िल्टर किए गए मॉडेलएरे स्वतः अपडेट हो जाएंगे। इस व्यवहार के लिए परीक्षा उत्तीर्ण हो रही है।

+0

आप सही हैं, यह एक AdapterPopulatedModelArray है। मैंने सवाल अपडेट किया है - टाइपो के लिए खेद है! – rlivsey

8

विचारों का अतः इस जोड़े:

(संदर्भ: https://github.com/emberjs/data/issues/190)

कैसे नए रिकॉर्ड के लिए डेटासंग्रह

एक सामान्य Model.find() में सुनने के लिए/findQuery() वापस आ जाएगी आप एक AdapterPopulatedModelArray, लेकिन वह सरणी स्वयं ही खड़ी होगी ... यह नहीं पता कि डेटाबेस में कुछ भी नया लोड किया गया है

कोई मॉडल नहीं है ams (या store.findAll()) आपको सभी रिकॉर्ड एक फ़िल्टर किए गए मॉडेलएरे को वापस कर देगा, और एम्बर-डेटा इसे एक सूची में "पंजीकृत" करेगा, और डेटाबेस में लोड किए गए किसी भी नए रिकॉर्ड को इस सरणी में जोड़ा जाएगा।

कॉलिंग मॉडल.फिल्टर (func) आपको एक फ़िल्टर किए गए मॉडेलएरे को वापस लाएगा, जो स्टोर के साथ भी पंजीकृत है ... और स्टोर में किसी भी नए रिकॉर्ड से एम्बर-डेटा "अपडेट मॉडेल एर्रेज़" का कारण बन जाएगा, जिसका अर्थ है कि यह आपके कॉल करेगा नए रिकॉर्ड के साथ फ़िल्टर फ़ंक्शन, और यदि आप सत्य वापस करते हैं, तो यह इसे आपके मौजूदा सरणी में चिपकेगा।

तो मैं क्या कर रहा हूं: स्टोर बनाने के तुरंत बाद, मैं store.findAll() को कॉल करता हूं, जो मुझे एक प्रकार के लिए सभी मॉडलों की सरणी देता है ... और मैं इसे स्टोर से जोड़ता हूं .. फिर कोड में कहीं और, मैं उन सूचियों में ऐरे ऑब्सर्वर जोड़ सकता हूं ..की तरह कुछ:

App.MyModel = DS.Model.extend() 
App.store = DS.Store.create() 
App.store.allMyModels = App.store.findAll(App.MyModel) 

//some other place in the app... a list controller perhaps 
App.store.allMyModels.addArrayObserver({ 
    arrayWillChange: function(arr, start, removeCount, addCount) {} 
    arrayDidChange: function(arr, start, removeCount, addCount) {} 
}) 

उन "अपरिवर्तनीय" सरणियों में से एक में एक मॉडल पुश करने के लिए कैसे:

सबसे पहले ध्यान दें: सभी एंबर-डेटा मॉडल उदाहरणों (रिकॉर्ड) एक clientid संपत्ति है ... जो एक अद्वितीय पूर्णांक है जो डेटास्टोर कैश में मॉडल की पहचान करता है चाहे उसके पास वास्तविक सर्वर-आईडी अभी भी है (उदाहरण: मॉडल.क्रिएट रिकॉर्ड करने के बाद)।

तो एडाप्टरपोप्लेटेडमोडेलएरे के पास एक "सामग्री" संपत्ति है ... जो इन क्लाइंट आईडी की एक सरणी है ... और जब आप एडाप्टरपोप्लेटेड मॉडेलएरे पर फिर से सक्रिय होते हैं, तो इन क्लाइंट पर हेडरेटर लूप होता है और हाथों को आप पूर्ण मॉडल उदाहरणों (रिकॉर्ड) कि प्रत्येक ग्राहक आईडी के लिए नक्शा।

मैं इतना क्या किया है (इस मतलब यह नहीं है कि यह "सही") उन findAll सरणियों घड़ी, और नए clientid की धक्का AdapterPopulatedModelArray की सामग्री संपत्ति में करने के लिए है ... कुछ की तरह:

arrayDidChange:function(arr, start, removeCount, addCount){ 
    if (addCount == 0) {return;} //only care about adds right now... not removes... 
     arr.slice(start, start+addCount).forEach(function(item) { 
      //push clientId of this item into AdapterPopulatedModelArray content list 
      self.getPath('list.content').pushObject(item.get('clientId')); 
     }); 
    } 

मैं क्या कह सकता हूं: "यह मेरे लिए काम कर रहा है" :) क्या यह अगले एम्बर-डेटा अपडेट पर टूट जाएगा? पूरी तरह से संभव

2

अभी भी इस के साथ संघर्ष कर रहे लोगों के लिए, आप अपने आप को store.filter विधि का उपयोग कर एक स्थिर DS.AdapterPopulatedRecordArray के बजाय एक गतिशील DS.FilteredArray मिल सकती है। यह takes 3 parameters: टाइप, क्वेरी और आखिर में फ़िल्टर कॉलबैक।

loadMessages: function() { 
    var self = this, 
     room_id = App.getPath('current_room.id'); 

    this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) { 
    return msg.get('roomId') === room_id; 
    }) 
    // set content only after promise has resolved 
    .then(function (messages) { 
    self.set('content', messages); 
    });   
} 

तुम भी अतिरिक्त मनमुताबिक मॉडल हुक में यह कर सकता है, क्योंकि मॉडल हुक एक वादा सीधे स्वीकार करेंगे:

model: function() { 
    var self = this, 
     room_id = App.getPath("current_room.id"); 

    return this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) { 
    return msg.get('roomId') === room_id; 
    }); 
} 
संबंधित मुद्दे