Skip to content

Commit

Permalink
Removing detect function (and dependence on model package) in favor o…
Browse files Browse the repository at this point in the history
…f watchModelTypes
  • Loading branch information
pliljegr committed Oct 2, 2019
1 parent f5e0e51 commit afd687b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 9 deletions.
7 changes: 7 additions & 0 deletions packages/-ember-data/tests/dummy/app/models/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';

export default class extends Model {
@attr name;
@belongsTo('foo', { async: false }) parent;
@hasMany('foo', { async: false }) children;
}
15 changes: 14 additions & 1 deletion packages/-ember-data/tests/dummy/app/routes/application/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
import Route from '@ember/routing/route';

export default Route.extend({});
export default Route.extend({
model() {
// adding a model to the store to enable manually testing the debug-adapter
return this.store.push({
data: {
id: 1,
type: 'foo',
attributes: {
name: 'taco'
}
}
})
}
});
73 changes: 65 additions & 8 deletions packages/debug/addon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import DataAdapter from '@ember/debug/data-adapter';
import { capitalize, underscore } from '@ember/string';
import { assert } from '@ember/debug';
import { get } from '@ember/object';
import Model from '@ember-data/model';
import { StoreTypesMap } from './setup';

/**
Implements `@ember/debug/data-adapter` with for EmberData
Expand Down Expand Up @@ -38,15 +38,72 @@ export default DataAdapter.extend({
];
},

_nameToClass(type) {
return get(this, 'store').modelFor(type);
},

/**
Detect whether a class is a Model
@private
@method detect
@param {Model} typeClass
@return {Boolean} Whether the typeClass is a Model class or not
Fetch the model types and observe them for changes.
Maintains the list of model types without needing the Model package for detection.
@public
@method watchModelTypes
@param {Function} typesAdded Callback to call to add types.
Takes an array of objects containing wrapped types (returned from `wrapModelType`).
@param {Function} typesUpdated Callback to call when a type has changed.
Takes an array of objects containing wrapped types.
@return {Function} Method to call to remove all observers
*/
detect(typeClass) {
return typeClass !== Model && Model.detect(typeClass);
watchModelTypes(typesAdded, typesUpdated) {
const store = get(this, 'store');
const __createRecordData = store._createRecordData;
const _releaseMethods = [];
const discoveredTypes = StoreTypesMap.get(store);

// Add any models that were added during initialization of the app, before the inspector was opened
discoveredTypes.forEach((_, type) => {
this.watchTypeIfUnseen(store, discoveredTypes, type, typesAdded, typesUpdated, _releaseMethods);
});

// Overwrite _createRecordData so newly added models will get added to the list
store._createRecordData = function(identifier) {
this.watchTypeIfUnseen(store, discoveredTypes, identifier.type, typesAdded, typesUpdated, _releaseMethods);
return __createRecordData.call(store, identifier);
};

let release = () => {
_releaseMethods.forEach(fn => fn());
store._createRecordData = __createRecordData;
// reset the list so the models can be added if the inspector is re-opened
// the entries are set to false instead of removed, since the models still exist in the app
// we just need the inspector to become aware of them
discoveredTypes.forEach((value, key) => {
discoveredTypes.set(key, false);
});
this.releaseMethods.removeObject(release);
};
this.releaseMethods.pushObject(release);
return release;
},

/**
* Loop over the discovered types and use the callbacks from watchModelTypes to notify
* the consumer of this adapter about the mdoels.
*
* @param {store} store
* @param {Map} discoveredTypes
* @param {String} type
* @param {Function} typesAdded
* @param {Function} typesUpdated
* @param {Array} releaseMethods
*/
watchTypeIfUnseen(store, discoveredTypes, type, typesAdded, typesUpdated, releaseMethods) {
if (discoveredTypes.get(type) !== true) {
let klass = store.modelFor(type);
let wrapped = this.wrapModelType(klass, type);
releaseMethods.push(this.observeModelType(type, typesUpdated));
typesAdded([wrapped]);
discoveredTypes.set(type, true);
}
},

/**
Expand Down
22 changes: 22 additions & 0 deletions packages/debug/addon/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const StoreTypesMap = new WeakMap();

function setupDataAdapter(application) {
const store = application.lookup('service:store');
const typesMap = new Map();
// its possible the app has more than one store, so this works on the 'main' store
StoreTypesMap.set(store, typesMap);

const __createRecordData = store._createRecordData;
// override _createRecordData to add the known models to the typesMap
store._createRecordData = function(identifier) {
if (!typesMap.has(identifier.type)) {
typesMap.set(identifier.type, false);
}
return __createRecordData.call(store, identifier);
};
}

export default {
name: '@ember-data/data-adapter',
initialize: setupDataAdapter,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember-data/debug/setup';

0 comments on commit afd687b

Please sign in to comment.