Ext.define('Ext.ux.parse.association.Relation', {
extend: 'Ext.data.association.Association',
alias: 'association.relation',
config: {
/**
* @cfg {Object} store
* Optional configuration object that will be passed to the generated Store. Defaults to an empty Object.
*/
store: undefined,
/**
* @cfg {String} storeName
* Optional The name of the store by which you can reference it on this class as a property.
*/
storeName: undefined,
/**
* @cfg {Boolean} autoLoad
* `true` to automatically load the related store from a remote source when instantiated.
*/
autoLoad: false,
/**
* @cfg {Boolean} autoSync
* true to automatically synchronize the related store with the remote source
*/
autoSync: false
},
getStore:function(model) {
if(model[this.getName()]){
return model[this.getName()]();
}
return null;
},
getData: function(model){
var items = [],
store = this.getStore(model);
if(store){
var collection = store.getData(), data;
collection.each(function(model){
data = model.isParseModel ? model.getDataFlat() : model.getData();
items.push(data);
});
}
return items;
},
getStatus: function(model){
var store = this.getStore(model);
if(store){
if (store.isLoaded()){
return "loaded"
} else if (store.isLoading()){
return "loading"
}
}
return "unloaded";
},
applyAssociationKey: function(associationKey) {
if (!associationKey) {
var associatedName = this.getName();
associationKey = associatedName.toLowerCase();
}
return associationKey;
},
applyName: function(name) {
if (!name) {
name = Ext.util.Inflector.pluralize(this.getAssociatedName().toLowerCase());
}
return name;
},
applyStoreName: function(name) {
if (!name) {
name = this.getName() + 'Store';
}
return name;
},
/**
* @private
* @deprecated as of v2.0.0 on an association. Instead use the store configuration.
*
* Creates a function that returns an Ext.data.Store which is configured to load a set of data filtered
* by the owner model's primary key - e.g. in a `hasMany` association where Group `hasMany` Users, this function
* returns a Store configured to return the filtered set of a single Group's Users.
* @return {Function} The store-generating function.
*/
applyStore: function(storeConfig) {
var me = this,
associatedModel = me.getAssociatedModel(),
storeName = me.getStoreName(),
autoLoad = me.getAutoLoad(),
autoSync = me.getAutoSync();
return function() {
var record = this,
config, store,
listeners = {
addrecords: me.onAddRecords,
removerecords: me.onRemoveRecords,
write: me.onStoreWrite,
scope: me
};
if (record[storeName] === undefined) {
config = Ext.apply({}, storeConfig, {
model : associatedModel,
params : {
query: function() {
return record.$parseObject.relation(me.getName()).query();
}
},
autoSync : autoSync,
listeners : listeners
});
store = record[storeName] = Ext.create('Ext.data.Store', config);
store.boundTo = record;
if (autoLoad) {
record[storeName].load();
}
}
return record[storeName];
};
},
updateStore: function(store) {
this.getOwnerModel().prototype[this.getName()] = store;
},
/**
* Read associated data
* @private
* @param {Ext.data.Model} record The record we're writing to.
* @param {Ext.data.reader.Reader} reader The reader for the associated model.
* @param {Object} associationData The raw associated data.
*/
read: function(record, reader, associationData) {
var store = record[this.getName()](),
records = reader.read(associationData).getRecords();
store.add(records);
},
onAddRecords: function(store, records) {
this.syncRelation(store, 'create', records);
},
onRemoveRecords: function(store, records) {
this.syncRelation(store, 'destroy', records);
},
onStoreWrite: function(store, operation){
this.syncRelation(store, operation.getAction(), operation.getRecords());
},
syncRelation: function(store, type, records) {
if(type != "create" && type != "destroy") return;
var model = store.boundTo,
parse = model.getParseObject(),
relationFn = type == "destroy" ? "remove" : "add",
dirty = false,
ln = records.length, i, record, relatedParse,
relation = parse.relation(this.getName());
for (i = 0; i < ln; i++) {
record = records[i];
if(record.isParseModel) {
relatedParse = record.getParseObject();
if(!relatedParse.isNew()) {
relation[relationFn].call(relation, relatedParse);
dirty = true;
} else if(type === "create") {
// <debug>
Ext.Logger.warn('You cannot make relationships to Models that do not exist on parse. Save this model Prior to adding, record will be removed');
// </debug>
store.remove(record);
}
}
}
if(!model.dirty && dirty) model.setDirty(dirty);
}
});