Skip to content

Commit

Permalink
Merge pull request #5305 from bmac/serializer-adapter-unique
Browse files Browse the repository at this point in the history
Serializers and adapters should be unique per store
  • Loading branch information
rwjblue authored Dec 29, 2017
2 parents e934b67 + 6be9912 commit 0675ef3
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 26 deletions.
27 changes: 20 additions & 7 deletions addon/-private/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
},

Expand Down Expand Up @@ -2722,31 +2728,38 @@ 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;
}

// no model specific serializer or application serializer, check for the `defaultSerializer`
// 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;
},
Expand Down
5 changes: 3 additions & 2 deletions addon/setup-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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');
Expand Down
16 changes: 15 additions & 1 deletion tests/helpers/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
23 changes: 10 additions & 13 deletions tests/integration/backwards-compat/non-dasherized-lookups-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import DS from 'ember-data';

const {
JSONAPIAdapter,
JSONAPISerializer,
Model,
attr,
belongsTo,
Expand All @@ -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;
},
Expand Down Expand Up @@ -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;
},
Expand Down
6 changes: 3 additions & 3 deletions tests/integration/multiple-stores-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});


Expand Down

0 comments on commit 0675ef3

Please sign in to comment.