The retrieveRecords() method is called on your data source whenever the store needs to retrieve individual records. This happens most often when the store is trying to follow a toOne() or toMany() relationship or when you call store.find() with a record type and ID.
Implementing retrieveRecords() on your data source is usually pretty straightforward. In fact, you will instead often implement the simpler single-form of the method retrieveRecord(). This method simply needs to lookup the record info and get the correct URL.
The following example shows how you might implement retrieveRecord() for a simple Contact record:
AddressBook.DataSource = SC.DataSource.extend({
// other methods...
retrieveRecord: function(store, storeKey, id) {
// map storeKey back to record type
var recordType = SC.Store.recordTypeFor(storeKey),
url;
// decide on the URL based on the record type
if (recordType === AddressBook.Contact) {
url = “/ab/contacts/%@?alt=json”
} else {
// handle other types here...
}
// if no url is found, we don’t know how to handle this record
if (!url) return NO;
// we can handle it, get the URL.
SC.Request.getUrl(url.fmt(id)).set(‘isJSON’, YES)
.notify(this, this._didRetrieveRecord, {
store: store,
storeKey: storeKey
}).send();
return YES;
},
_didRetrieveRecord: function(response, params) {
var store = params.store,
storeKey = params.storeKey;
// normal: load into store...response == dataHash
if (SC.$ok(response)) {
store.dataSourceDidComplete(storeKey, response.get('body'));
// error: indicate as such...response == error
} else store.dataSourceDidError(storeKey, response.get('body'));
},
// .. other methods
});
The retrieveRecord() API is simple to implement, which makes it convenient. However, it also initiates a new request to the server for each record you want to retrieve. Many times, it is better to retrieve records in bulk if you have the API to do so. To do this, you should override retrieveRecords() on your data source instead of retrieveRecord().
The example below implements retrieveRecords() by sorting the list of storeKeys passed into groups based on record type. It then sends one request per record type to the backend:
AddressBook.DataSource = SC.DataSource.extend({
// other methods...
retrieveRecords: function(store, storeKeys) {
// convert storeKeys into id’s sorted by recordType.
var recordTypes = SC.Set.create(), // to store record types.
sortedIds = {},
ret=null ; // return value
storeKeys.forEach(function(storeKey) {
var recordType = SC.Store.recordTypeFor(storeKey);
recordTypes.add(recordType);
var typeGuid = SC.guidFor(recordType);
var ids = sortedIds[typeGuid];
if (!ids) ids = sortedIds[typeGuid] = [];
// map storeKey to ID
var id = store.idFor(storeKey);
ids.push(id);
}, this);
// now for each recordType, initiate a request
recordTypes.forEach(function(recordType) {
// find the URL for the recordType. if we can’t find one we can’t handle it
var url;
if (recordType === AddressBook.Contact) {
url = "/ab/contacts?alt=json&ids=%@";
} else {
// handle other types here...
}
// if url was found - initiate request
if (url) {
var ids = sortedIds[SC.guidFor(recordType)];
SC.Request.getUrl(url.fmt(ids.join(','))).set('isJSON', YES)
.notify(this, this._didRetrieveRecords, { store: store, recordType: recordType })
.send();
// set the proper return value.
ret = (ret===NO) ? SC.MIXED_STATE : (ret===null ? YES : ret);
// if url was not found, set ret to NO or mixed.
} else ret = (ret === null) ? NO : SC.MIXED_STATE ;
}, this);
return ret;
},
// called when a group of records have returns. assume result is array of data hashes
_didRetrieveRecords: function(response, params) {
var store = params.store,
recordType = params.recordType;
// normal: load into store...response == dataHash
if (SC.$ok(response)) {
store.loadRecords(recordType, response.get('body'));
// error: indicate as such...response == error
} else store.dataSourceDidError(storeKey, response.get('body'));
},
// .. other methods
});
On to Committing Changes »
Go back to DataStore Programming Guide Home »