Skip to content

Instantly share code, notes, and snippets.

@danmcclain
Created January 13, 2016 21:27
Show Gist options
  • Save danmcclain/9c3b8c9bc6eb580dcb95 to your computer and use it in GitHub Desktop.
Save danmcclain/9c3b8c9bc6eb580dcb95 to your computer and use it in GitHub Desktop.
Supporting JSON API Links at root level for pagination
commit 6dc7a15bd3b680fe7ded81ea77531ee297a5a732
Author: Dan McClain <git@danmcclain.net>
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