From 6be99125a8cedede507387f99071adc09d11977a Mon Sep 17 00:00:00 2001 From: bmac Date: Thu, 28 Dec 2017 21:12:50 -0500 Subject: [PATCH] Serializers and adapters should be unique per store --- addon/-private/system/store.js | 27 ++++++++++++++----- addon/setup-container.js | 5 ++-- tests/helpers/store.js | 16 ++++++++++- .../non-dasherized-lookups-test.js | 23 +++++++--------- tests/integration/multiple-stores-test.js | 6 ++--- 5 files changed, 51 insertions(+), 26 deletions(-) diff --git a/addon/-private/system/store.js b/addon/-private/system/store.js index 236288ef6d1..40fa112405f 100644 --- a/addon/-private/system/store.js +++ b/addon/-private/system/store.js @@ -2655,31 +2655,37 @@ Store = Service.extend({ adapter = owner.lookup(`adapter:${normalizedModelName}`); if (adapter !== undefined) { + set(adapter, 'store', this); _adapterCache[normalizedModelName] = adapter; return adapter; } // no adapter found for the specific model, fallback and check for application adapter - adapter = owner.lookup('adapter:application'); + adapter = _adapterCache.application || owner.lookup('adapter:application'); if (adapter !== undefined) { + set(adapter, 'store', this); _adapterCache[normalizedModelName] = adapter; + _adapterCache.application = adapter; return adapter; } // no model specific adapter or application adapter, check for an `adapter` // property defined on the store let adapterName = this.get('adapter'); - adapter = owner.lookup(`adapter:${adapterName}`); + adapter = _adapterCache[adapterName] || owner.lookup(`adapter:${adapterName}`); if (adapter !== undefined) { + set(adapter, 'store', this); _adapterCache[normalizedModelName] = adapter; + _adapterCache[adapterName] = adapter; return adapter; } // final fallback, no model specific adapter, no application adapter, no // `adapter` property on store: use json-api adapter - adapter = owner.lookup('adapter:-json-api'); + adapter = _adapterCache['-json-api'] || owner.lookup('adapter:-json-api'); + set(adapter, 'store', this); _adapterCache[normalizedModelName] = adapter; - + _adapterCache['-json-api'] = adapter; return adapter; }, @@ -2722,14 +2728,17 @@ Store = Service.extend({ serializer = owner.lookup(`serializer:${normalizedModelName}`); if (serializer !== undefined) { + set(serializer, 'store', this); _serializerCache[normalizedModelName] = serializer; return serializer; } // no serializer found for the specific model, fallback and check for application serializer - serializer = owner.lookup('serializer:application'); + serializer = _serializerCache.application || owner.lookup('serializer:application'); if (serializer !== undefined) { + set(serializer, 'store', this); _serializerCache[normalizedModelName] = serializer; + _serializerCache.application = serializer; return serializer; } @@ -2737,16 +2746,20 @@ Store = Service.extend({ // property defined on the adapter let adapter = this.adapterFor(modelName); let serializerName = get(adapter, 'defaultSerializer'); - serializer = owner.lookup(`serializer:${serializerName}`); + serializer = _serializerCache[serializerName] || owner.lookup(`serializer:${serializerName}`); if (serializer !== undefined) { + set(serializer, 'store', this); _serializerCache[normalizedModelName] = serializer; + _serializerCache[serializerName] = serializer; return serializer; } // final fallback, no model specific serializer, no application serializer, no // `serializer` property on store: use json-api serializer - serializer = owner.lookup('serializer:-default'); + serializer = _serializerCache['-default'] || owner.lookup('serializer:-default'); + set(serializer, 'store', this); _serializerCache[normalizedModelName] = serializer; + _serializerCache['-default'] = serializer; return serializer; }, diff --git a/addon/setup-container.js b/addon/setup-container.js index 0c5a16d25a0..9b78e973ff7 100644 --- a/addon/setup-container.js +++ b/addon/setup-container.js @@ -31,6 +31,9 @@ function has(applicationOrRegistry, fullName) { @param {Ember.Registry} registry */ function initializeStore(registry) { + let registerOptionsForType = registry.registerOptionsForType || registry.optionsForType; + registerOptionsForType.call(registry, 'serializer', { singleton: false }); + registerOptionsForType.call(registry, 'adapter', { singleton: false }); registry.register('serializer:-default', JSONSerializer); registry.register('serializer:-rest', RESTSerializer); registry.register('adapter:-rest', RESTAdapter); @@ -66,8 +69,6 @@ function initializeStoreInjections(registry) { // registry.injection for Ember < 2.1.0 // application.inject for Ember 2.1.0+ let inject = registry.inject || registry.injection; - inject.call(registry, 'adapter', 'store', 'service:store'); - inject.call(registry, 'serializer', 'store', 'service:store'); inject.call(registry, 'controller', 'store', 'service:store'); inject.call(registry, 'route', 'store', 'service:store'); inject.call(registry, 'data-adapter', 'store', 'service:store'); diff --git a/tests/helpers/store.js b/tests/helpers/store.js index c3bc2b24812..2e909241125 100644 --- a/tests/helpers/store.js +++ b/tests/helpers/store.js @@ -46,6 +46,8 @@ export default function setupStore(options) { adapter: adapter })); + registry.optionsForType('serializer', { singleton: false }); + registry.optionsForType('adapter', { singleton: false }); registry.register('adapter:-default', DS.Adapter); registry.register('serializer:-default', DS.JSONAPISerializer); @@ -62,7 +64,19 @@ export default function setupStore(options) { env.restSerializer.store = env.store; env.serializer = env.store.serializerFor('-default'); env.serializer.store = env.store; - env.adapter = env.store.get('defaultAdapter'); + Object.defineProperty(env, 'adapter', { + get() { + if (!this._adapter) { + this._adapter = this.store.adapterFor('application'); + } + return this._adapter; + }, + set(adapter) { + this._adapter = adapter; + }, + enumerable: true, + configurable: true + }); return env; } diff --git a/tests/integration/backwards-compat/non-dasherized-lookups-test.js b/tests/integration/backwards-compat/non-dasherized-lookups-test.js index 9cb4c3a290a..807a1657966 100644 --- a/tests/integration/backwards-compat/non-dasherized-lookups-test.js +++ b/tests/integration/backwards-compat/non-dasherized-lookups-test.js @@ -8,7 +8,6 @@ import DS from 'ember-data'; const { JSONAPIAdapter, - JSONAPISerializer, Model, attr, belongsTo, @@ -23,16 +22,16 @@ module('integration/backwards-compat/non-dasherized-lookups - non dasherized loo name: attr('string') }); - const env = setupStore({ postNote: PostNote }); - const ApplicationAdapter = JSONAPIAdapter.extend({ shouldBackgroundReloadRecord() { return false; } }); - env.registry.register('adapter:application', ApplicationAdapter); - env.registry.register('serializer:application', JSONAPISerializer); + const env = setupStore({ + postNote: PostNote, + adapter: ApplicationAdapter + }); store = env.store; }, @@ -102,20 +101,18 @@ module('integration/backwards-compat/non-dasherized-lookups - non dasherized loo postNotes: hasMany('post_note') }); - const env = setupStore({ - longModelName: LongModelName, - notePost: NotePost, - postNote: PostNote - }); - const ApplicationAdapter = JSONAPIAdapter.extend({ shouldBackgroundReloadRecord() { return false; } }); - env.registry.register('adapter:application', ApplicationAdapter); - env.registry.register('serializer:application', JSONAPISerializer); + const env = setupStore({ + longModelName: LongModelName, + notePost: NotePost, + postNote: PostNote, + adapter: ApplicationAdapter + }); store = env.store; }, diff --git a/tests/integration/multiple-stores-test.js b/tests/integration/multiple-stores-test.js index 36bdbcf3c83..116d953cea6 100644 --- a/tests/integration/multiple-stores-test.js +++ b/tests/integration/multiple-stores-test.js @@ -145,9 +145,9 @@ test("each store should have a unique instance of the serializers", function(ass let serializer_a = env.store_a.serializerFor('home-planet'); let serializer_b = env.store_b.serializerFor('home-planet'); - assert.equal(get(serializer_a, 'store'), env.store_a); - assert.equal(get(serializer_b, 'store'), env.store_b); - assert.notEqual(serializer_a, serializer_b); + assert.equal(get(serializer_a, 'store'), env.store_a, 'serializer_a\'s store prop should be sotre_a'); + assert.equal(get(serializer_b, 'store'), env.store_b, 'serializer_b\'s store prop should be sotre_b'); + assert.notEqual(serializer_a, serializer_b, 'serialier_a and serialier_b should be unique instances'); });