Skip to content

Commit

Permalink
Merge pull request #3310 from bmac/snapshot-array
Browse files Browse the repository at this point in the history
Allow the store to pass adapter options to the adapter
  • Loading branch information
igorT committed Jun 13, 2015
2 parents d913d2f + 059ec88 commit f44a9f1
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 40 deletions.
1 change: 1 addition & 0 deletions packages/ember-data/lib/system/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ var Adapter = Ember.Object.extend({
@param {DS.Store} store
@param {DS.Model} type
@param {String} sinceToken
@param {DS.SnapshotRecordArray} snapshotRecordArray
@return {Promise} promise
*/
findAll: null,
Expand Down
11 changes: 7 additions & 4 deletions packages/ember-data/lib/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ InternalModel.prototype = {
this.send('deleteRecord');
},

save: function() {
save: function(options) {
var promiseLabel = "DS: Model#save " + this;
var resolver = Ember.RSVP.defer(promiseLabel);

this.store.scheduleSave(this, resolver);
this.store.scheduleSave(this, resolver, options);
return resolver.promise;
},

Expand Down Expand Up @@ -221,8 +221,11 @@ InternalModel.prototype = {
@method createSnapshot
@private
*/
createSnapshot: function() {
return new Snapshot(this);
createSnapshot: function(options) {
var adapterOptions = options && options.adapterOptions;
var snapshot = new Snapshot(this);
snapshot.adapterOptions = adapterOptions;
return snapshot;
},

/**
Expand Down
10 changes: 6 additions & 4 deletions packages/ember-data/lib/system/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,12 +519,13 @@ var Model = Ember.Object.extend(Ember.Evented, {
```
@method destroyRecord
@param {Object} options
@return {Promise} a promise that will be resolved when the adapter returns
successfully or rejected if the adapter returns with an error.
*/
destroyRecord: function() {
destroyRecord: function(options) {
this.deleteRecord();
return this.save();
return this.save(options);
},

/**
Expand Down Expand Up @@ -677,13 +678,14 @@ var Model = Ember.Object.extend(Ember.Evented, {
});
```
@method save
@param {Object} options
@return {Promise} a promise that will be resolved when the adapter returns
successfully or rejected if the adapter returns with an error.
*/
save: function() {
save: function(options) {
var model = this;
return PromiseObject.create({
promise: this._internalModel.save().then(function() {
promise: this._internalModel.save(options).then(function() {
return model;
})
});
Expand Down
44 changes: 44 additions & 0 deletions packages/ember-data/lib/system/snapshot-record-array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
@module ember-data
*/

/**
@class SnapshotRecordArray
@namespace DS
@private
@constructor
@param {Array} snapshots An array of snapshots
@param {Object} meta
*/
function SnapshotRecordArray(recordArray, meta, adapterOptions) {
this._snapshots = null;
this._recordArray = recordArray;
this.length = recordArray.get('length');
this.meta = meta;
this.adapterOptions = adapterOptions;
}

/**
@method fromRecordArray
@private
@static
@param {DS.RecordArray} recordArray
@param {Object} adapterOptions
@return SnapshotRecordArray
*/
SnapshotRecordArray.fromRecordArray = function(recordArray, adapterOptions) {
var meta = recordArray.get('meta');
return new SnapshotRecordArray(recordArray, meta, adapterOptions);
};

SnapshotRecordArray.prototype.snapshots = function() {
if (this._snapshots) {
return this._snapshots;
}
var recordArray = this._recordArray;
this._snapshots = recordArray.invoke('createSnapshot');

return this._snapshots;
};

export default SnapshotRecordArray;
63 changes: 35 additions & 28 deletions packages/ember-data/lib/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ Store = Service.extend({
}

if (internalModel.isEmpty()) {
fetchedInternalModel = this.scheduleFetch(internalModel);
fetchedInternalModel = this.scheduleFetch(internalModel, options);
//TODO double check about reloading
} else if (internalModel.isLoading()) {
fetchedInternalModel = internalModel._loadingPromise;
Expand Down Expand Up @@ -641,16 +641,17 @@ Store = Service.extend({
@private
@param {InternalModel} internalModel model
@return {Promise} promise
*/
fetchRecord: function(internalModel) {
*/
// TODO rename this to have an underscore
fetchRecord: function(internalModel, options) {
var typeClass = internalModel.type;
var id = internalModel.id;
var adapter = this.adapterFor(typeClass.modelName);

Ember.assert("You tried to find a record but you have no adapter (for " + typeClass + ")", adapter);
Ember.assert("You tried to find a record but your adapter (for " + typeClass + ") does not implement 'find'", typeof adapter.find === 'function');

var promise = _find(adapter, this, typeClass, id, internalModel);
var promise = _find(adapter, this, typeClass, id, internalModel, options);
return promise;
},

Expand All @@ -659,24 +660,25 @@ Store = Service.extend({
return Promise.all(map(internalModels, this.scheduleFetch, this));
},

scheduleFetch: function(internalModel) {
scheduleFetch: function(internalModel, options) {
var typeClass = internalModel.type;

if (internalModel._loadingPromise) { return internalModel._loadingPromise; }

var resolver = Ember.RSVP.defer('Fetching ' + typeClass + 'with id: ' + internalModel.id);
var recordResolverPair = {
var pendingFetchItem = {
record: internalModel,
resolver: resolver
resolver: resolver,
options: options
};
var promise = resolver.promise;

internalModel.loadingData(promise);

if (!this._pendingFetch.get(typeClass)) {
this._pendingFetch.set(typeClass, [recordResolverPair]);
this._pendingFetch.set(typeClass, [pendingFetchItem]);
} else {
this._pendingFetch.get(typeClass).push(recordResolverPair);
this._pendingFetch.get(typeClass).push(pendingFetchItem);
}
Ember.run.scheduleOnce('afterRender', this, this.flushAllPendingFetches);

Expand All @@ -692,19 +694,19 @@ Store = Service.extend({
this._pendingFetch = Map.create();
},

_flushPendingFetchForType: function (recordResolverPairs, typeClass) {
_flushPendingFetchForType: function (pendingFetchItems, typeClass) {
var store = this;
var adapter = store.adapterFor(typeClass.modelName);
var shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
var records = Ember.A(recordResolverPairs).mapBy('record');
var records = Ember.A(pendingFetchItems).mapBy('record');

function _fetchRecord(recordResolverPair) {
recordResolverPair.resolver.resolve(store.fetchRecord(recordResolverPair.record));
recordResolverPair.resolver.resolve(store.fetchRecord(recordResolverPair.record, recordResolverPair.options)); // TODO adapter options
}

function resolveFoundRecords(records) {
forEach(records, function(record) {
var pair = Ember.A(recordResolverPairs).findBy('record', record);
var pair = Ember.A(pendingFetchItems).findBy('record', record);
if (pair) {
var resolver = pair.resolver;
resolver.resolve(record);
Expand Down Expand Up @@ -734,16 +736,16 @@ Store = Service.extend({

function rejectRecords(records, error) {
forEach(records, function(record) {
var pair = Ember.A(recordResolverPairs).findBy('record', record);
var pair = Ember.A(pendingFetchItems).findBy('record', record);
if (pair) {
var resolver = pair.resolver;
resolver.reject(error);
}
});
}

if (recordResolverPairs.length === 1) {
_fetchRecord(recordResolverPairs[0]);
if (pendingFetchItems.length === 1) {
_fetchRecord(pendingFetchItems[0]);
} else if (shouldCoalesce) {

// TODO: Improve records => snapshots => records => snapshots
Expand All @@ -769,14 +771,14 @@ Store = Service.extend({
then(makeMissingRecordsRejector(requestedRecords)).
then(null, makeRecordsRejector(requestedRecords));
} else if (ids.length === 1) {
var pair = Ember.A(recordResolverPairs).findBy('record', groupOfRecords[0]);
var pair = Ember.A(pendingFetchItems).findBy('record', groupOfRecords[0]);
_fetchRecord(pair);
} else {
Ember.assert("You cannot return an empty array from adapter's method groupRecordsForFindMany", false);
}
});
} else {
forEach(recordResolverPairs, _fetchRecord);
forEach(pendingFetchItems, _fetchRecord);
}
},

Expand Down Expand Up @@ -1043,13 +1045,14 @@ Store = Service.extend({
@method findAll
@param {String} modelName
@param {Object} options
@return {DS.AdapterPopulatedRecordArray}
*/
findAll: function(modelName) {
findAll: function(modelName, options) {
Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of '+ Ember.inspect(modelName), typeof modelName === 'string');
var typeClass = this.modelFor(modelName);

return this._fetchAll(typeClass, this.peekAll(modelName));
return this._fetchAll(typeClass, this.peekAll(modelName), options);
},

/**
Expand All @@ -1059,7 +1062,7 @@ Store = Service.extend({
@param {DS.RecordArray} array
@return {Promise} promise
*/
_fetchAll: function(typeClass, array) {
_fetchAll: function(typeClass, array, options) {
var adapter = this.adapterFor(typeClass.modelName);
var sinceToken = this.typeMapFor(typeClass).metadata.since;

Expand All @@ -1068,7 +1071,7 @@ Store = Service.extend({
Ember.assert("You tried to load all records but you have no adapter (for " + typeClass + ")", adapter);
Ember.assert("You tried to load all records but your adapter does not implement `findAll`", typeof adapter.findAll === 'function');

return promiseArray(_findAll(adapter, this, typeClass, sinceToken));
return promiseArray(_findAll(adapter, this, typeClass, sinceToken, options));
},

/**
Expand Down Expand Up @@ -1349,12 +1352,16 @@ Store = Service.extend({
@private
@param {InternalModel} internalModel
@param {Resolver} resolver
@param {Object} options
*/
scheduleSave: function(internalModel, resolver) {
var snapshot = internalModel.createSnapshot();
scheduleSave: function(internalModel, resolver, options) {
var snapshot = internalModel.createSnapshot(options);
internalModel.flushChangedAttributes();
internalModel.adapterWillCommit();
this._pendingSave.push([snapshot, resolver]);
this._pendingSave.push({
snapshot: snapshot,
resolver: resolver
});
once(this, 'flushPendingSave');
},

Expand All @@ -1369,9 +1376,9 @@ Store = Service.extend({
var pending = this._pendingSave.slice();
this._pendingSave = [];

forEach(pending, function(tuple) {
var snapshot = tuple[0];
var resolver = tuple[1];
forEach(pending, function(pendingItem) {
var snapshot = pendingItem.snapshot;
var resolver = pendingItem.resolver;
var record = snapshot._internalModel;
var adapter = this.adapterFor(record.type.modelName);
var operation;
Expand Down
12 changes: 8 additions & 4 deletions packages/ember-data/lib/system/store/finders.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import {
serializerForAdapter
} from "ember-data/system/store/serializers";

import SnapshotRecordArray from "ember-data/system/snapshot-record-array";

var Promise = Ember.RSVP.Promise;
var map = Ember.EnumerableUtils.map;

export function _find(adapter, store, typeClass, id, internalModel) {
var snapshot = internalModel.createSnapshot();
export function _find(adapter, store, typeClass, id, internalModel, options) {
var snapshot = internalModel.createSnapshot(options);
var promise = adapter.find(store, typeClass, id, snapshot);
var serializer = serializerForAdapter(store, adapter, internalModel.type.modelName);
var label = "DS: Handle Adapter#find of " + typeClass + " with id: " + id;
Expand Down Expand Up @@ -118,9 +120,11 @@ export function _findBelongsTo(adapter, store, internalModel, link, relationship
}, null, "DS: Extract payload of " + internalModel + " : " + relationship.type);
}

export function _findAll(adapter, store, typeClass, sinceToken) {
var promise = adapter.findAll(store, typeClass, sinceToken);
export function _findAll(adapter, store, typeClass, sinceToken, options) {
var adapterOptions = options && options.adapterOptions;
var modelName = typeClass.modelName;
var snapshotArray = SnapshotRecordArray.fromRecordArray(store.peekAll(modelName), adapterOptions);
var promise = adapter.findAll(store, typeClass, sinceToken, snapshotArray);
var serializer = serializerForAdapter(store, adapter, modelName);
var label = "DS: Handle Adapter#findAll of " + typeClass;

Expand Down
Loading

0 comments on commit f44a9f1

Please sign in to comment.