Created
January 13, 2016 21:27
-
-
Save danmcclain/9c3b8c9bc6eb580dcb95 to your computer and use it in GitHub Desktop.
Supporting JSON API Links at root level for pagination
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 6dc7a15bd3b680fe7ded81ea77531ee297a5a732 | |
Author: Dan McClain <[email protected]> | |
Date: Wed Jan 13 16:25:27 2016 -0500 | |
WIP Spike out override of AdapterPopulatedRecordArray to support links | |
diff --git a/app/ext/adapter-populated-record-array.js b/app/ext/adapter-populated-record-array.js | |
new file mode 100644 | |
index 0000000..77ea745 | |
--- /dev/null | |
+++ b/app/ext/adapter-populated-record-array.js | |
@@ -0,0 +1,35 @@ | |
+import Ember from 'ember'; | |
+import cloneNull from "ember-data/-private/system/clone-null"; | |
+ | |
+import { | |
+ AdapterPopulatedRecordArray | |
+} from 'ember-data/-private/system/record-arrays'; | |
+ | |
+export default AdapterPopulatedRecordArray.extend({ | |
+ _linksObject(links) { | |
+ return cloneNull(links); | |
+ }, | |
+ | |
+ loadRecords(records, payload) { | |
+ let store = get(this, 'store'); | |
+ let type = get(this, 'type'); | |
+ let modelName = type.modelName; | |
+ let meta = store._metadataFor(modelName); | |
+ | |
+ //TODO Optimize | |
+ let internalModels = Ember.A(records).mapBy('_internalModel'); | |
+ this.setProperties({ | |
+ content: Ember.A(internalModels), | |
+ isLoaded: true, | |
+ meta: cloneNull(meta), | |
+ links: this._linksObject(payload.links) | |
+ }); | |
+ | |
+ internalModels.forEach((record) => { | |
+ this.manager.recordArraysForRecord(record).add(this); | |
+ }); | |
+ | |
+ // TODO: should triggering didLoad event be the last action of the runLoop? | |
+ Ember.run.once(this, 'trigger', 'didLoad'); | |
+ }, | |
+}); | |
diff --git a/app/ext/record-array-manager.js b/app/ext/record-array-manager.js | |
new file mode 100644 | |
index 0000000..e2f7bf8 | |
--- /dev/null | |
+++ b/app/ext/record-array-manager.js | |
@@ -0,0 +1,18 @@ | |
+import RecordArrayManager from 'ember-data/-private/system/record-array-manager'; | |
+import AdapterPopulatedRecordArray from './adapter-populated-record-array'; | |
+ | |
+export default RecordArrayManager.extend({ | |
+ createAdapterPopulatedRecordArray(typeClass, query) { | |
+ let array = AdapterPopulatedRecordArray.create({ | |
+ type: typeClass, | |
+ query: query, | |
+ content: Ember.A(), | |
+ store: this.store, | |
+ manager: this | |
+ }); | |
+ | |
+ this._adapterPopulatedRecordArrays.push(array); | |
+ | |
+ return array; | |
+ } | |
+}); | |
diff --git a/app/services/store.js b/app/services/store.js | |
new file mode 100644 | |
index 0000000..f954372 | |
--- /dev/null | |
+++ b/app/services/store.js | |
@@ -0,0 +1,74 @@ | |
+import Store from 'ember-data/store'; | |
+import RecordArrayManager from '../ext/record-array-manager'; | |
+ | |
+ | |
+import { | |
+ promiseArray, | |
+ promiseObject | |
+} from "ember-data/-private/system/promise-proxies"; | |
+ | |
+import Ember from 'ember'; | |
+import { assert } from "ember-data/-private/debug"; | |
+import { | |
+ _bind, | |
+ _guard, | |
+ _objectIsAlive | |
+} from "ember-data/-private/system/store/common"; | |
+ | |
+import { | |
+ normalizeResponseHelper | |
+} from "ember-data/-private/system/store/serializer-response"; | |
+ | |
+import { | |
+ serializerForAdapter | |
+} from "ember-data/-private/system/store/serializers"; | |
+ | |
+var Promise = Ember.RSVP.Promise; | |
+ | |
+function customquery(adapter, store, typeClass, query, recordArray) { | |
+ var modelName = typeClass.modelName; | |
+ var promise = adapter.query(store, typeClass, query, recordArray); | |
+ | |
+ var serializer = serializerForAdapter(store, adapter, modelName); | |
+ var label = "DS: Handle Adapter#query of " + typeClass; | |
+ | |
+ promise = Promise.resolve(promise, label); | |
+ promise = _guard(promise, _bind(_objectIsAlive, store)); | |
+ | |
+ return promise.then(function(adapterPayload) { | |
+ var records; | |
+ let payload; | |
+ store._adapterRun(function() { | |
+ payload = normalizeResponseHelper(serializer, store, typeClass, adapterPayload, null, 'query'); | |
+ //TODO Optimize | |
+ records = store.push(payload); | |
+ }); | |
+ | |
+ assert('The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', Ember.isArray(records)); | |
+ recordArray.loadRecords(records, payload); | |
+ return recordArray; | |
+ | |
+ }, null, "DS: Extract payload of query " + typeClass); | |
+} | |
+ | |
+export default Store.extend({ | |
+ init() { | |
+ this._super(...arguments); | |
+ this.recordArrayManager = RecordArrayManager.create({ | |
+ store: this | |
+ }); | |
+ }, | |
+ _query: function(modelName, query, array) { | |
+ 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); | |
+ array = array || this.recordArrayManager | |
+ .createAdapterPopulatedRecordArray(typeClass, query); | |
+ | |
+ var adapter = this.adapterFor(modelName); | |
+ | |
+ assert("You tried to load a query but you have no adapter (for " + typeClass + ")", adapter); | |
+ assert("You tried to load a query but your adapter does not implement `query`", typeof adapter.query === 'function'); | |
+ | |
+ return promiseArray(customquery(adapter, this, typeClass, query, array)); | |
+ }, | |
+}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment