From 7a608d467eb0bd6135164ceb84692f6d7d0c5bc7 Mon Sep 17 00:00:00 2001 From: IgorT Date: Thu, 27 Nov 2014 22:43:35 -0500 Subject: [PATCH] Cache relationships meta in production --- .../lib/system/relationships/ext.js | 135 ++++++++++-------- .../relationships/belongs_to_test.js | 53 ++++++- 2 files changed, 129 insertions(+), 59 deletions(-) diff --git a/packages/ember-data/lib/system/relationships/ext.js b/packages/ember-data/lib/system/relationships/ext.js index 7aedd73a4b6..997189395c6 100644 --- a/packages/ember-data/lib/system/relationships/ext.js +++ b/packages/ember-data/lib/system/relationships/ext.js @@ -11,6 +11,80 @@ import { var get = Ember.get; var filter = Ember.ArrayPolyfills.filter; +var relationshipsDescriptor = Ember.computed(function() { + if (Ember.testing === true && relationshipsDescriptor._cacheable === true) { + relationshipsDescriptor._cacheable = false; + } + + var map = new MapWithDefault({ + defaultValue: function() { return []; } + }); + + // Loop through each computed property on the class + this.eachComputedProperty(function(name, meta) { + // If the computed property is a relationship, add + // it to the map. + if (meta.isRelationship) { + meta.key = name; + var relationshipsForType = map.get(typeForRelationshipMeta(this.store, meta)); + + relationshipsForType.push({ + name: name, + kind: meta.kind + }); + } + }); + + return map; +}).readOnly(); + +var relatedTypesDescriptor = Ember.computed(function() { + if (Ember.testing === true && relatedTypesDescriptor._cacheable === true) { + relatedTypesDescriptor._cacheable = false; + } + + var type; + var types = Ember.A(); + + // Loop through each computed property on the class, + // and create an array of the unique types involved + // in relationships + this.eachComputedProperty(function(name, meta) { + if (meta.isRelationship) { + meta.key = name; + type = typeForRelationshipMeta(this.store, meta); + + Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.", type); + + if (!types.contains(type)) { + Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type); + types.push(type); + } + } + }); + + return types; +}).readOnly(); + +var relationshipsByNameDescriptor = Ember.computed(function() { + if (Ember.testing === true && relationshipsByNameDescriptor._cacheable === true) { + relationshipsByNameDescriptor._cacheable = false; + } + + var map = Map.create(); + + this.eachComputedProperty(function(name, meta) { + if (meta.isRelationship) { + meta.key = name; + var relationship = relationshipFromMeta(this.store, meta); + relationship.type = typeForRelationshipMeta(this.store, meta); + map.set(name, relationship); + } + }); + + return map; +}).readOnly(); + /** @module ember-data */ @@ -266,28 +340,8 @@ Model.reopenClass({ @type Ember.Map @readOnly */ - relationships: Ember.computed(function() { - var map = new MapWithDefault({ - defaultValue: function() { return []; } - }); - // Loop through each computed property on the class - this.eachComputedProperty(function(name, meta) { - // If the computed property is a relationship, add - // it to the map. - if (meta.isRelationship) { - meta.key = name; - var relationshipsForType = map.get(typeForRelationshipMeta(this.store, meta)); - - relationshipsForType.push({ - name: name, - kind: meta.kind - }); - } - }); - - return map; - }).cacheable(false).readOnly(), + relationships: relationshipsDescriptor, /** A hash containing lists of the model's relationships, grouped @@ -361,29 +415,7 @@ Model.reopenClass({ @type Ember.Array @readOnly */ - relatedTypes: Ember.computed(function() { - var type; - var types = Ember.A(); - - // Loop through each computed property on the class, - // and create an array of the unique types involved - // in relationships - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - type = typeForRelationshipMeta(this.store, meta); - - Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.", type); - - if (!types.contains(type)) { - Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type); - types.push(type); - } - } - }); - - return types; - }).cacheable(false).readOnly(), + relatedTypes: relatedTypesDescriptor, /** A map whose keys are the relationships of a model and whose values are @@ -416,20 +448,7 @@ Model.reopenClass({ @type Ember.Map @readOnly */ - relationshipsByName: Ember.computed(function() { - var map = Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - var relationship = relationshipFromMeta(this.store, meta); - relationship.type = typeForRelationshipMeta(this.store, meta); - map.set(name, relationship); - } - }); - - return map; - }).cacheable(false).readOnly(), + relationshipsByName: relationshipsByNameDescriptor, /** A map whose keys are the fields of the model and whose values are strings diff --git a/packages/ember-data/tests/integration/relationships/belongs_to_test.js b/packages/ember-data/tests/integration/relationships/belongs_to_test.js index 657a6c9cdc9..12b10cba588 100644 --- a/packages/ember-data/tests/integration/relationships/belongs_to_test.js +++ b/packages/ember-data/tests/integration/relationships/belongs_to_test.js @@ -357,7 +357,58 @@ test("relationshipsByName does not cache a factory", function() { "model factory based on relationship type matches the model based on store.modelFor" ); }); -test("asdf", function() { +test("relationshipsByName is cached in production", function() { + var model = store.modelFor('user'); + var oldTesting = Ember.testing; + //We set the cacheable to true because that is the default state for any CP and then assert that it + //did not get dynamically changed when accessed + var oldCacheable = Ember.meta(model).descs.relationshipsByName._cacheable; + Ember.meta(model).descs.relationshipsByName._cacheable = true; + Ember.testing = false; + try { + equal(get(model, 'relationshipsByName'), get(model, 'relationshipsByName'), 'relationshipsByName are cached'); + equal(get(model, 'relationshipsByName'), get(model, 'relationshipsByName'), 'relationshipsByName are cached'); + } finally { + Ember.testing = oldTesting; + Ember.meta(model).descs.relationshipsByName._cacheable = oldCacheable; + } +}); + +test("relatedTypes is cached in production", function() { + var model = store.modelFor('user'); + var oldTesting = Ember.testing; + //We set the cacheable to true because that is the default state for any CP and then assert that it + //did not get dynamically changed when accessed + var oldCacheable = Ember.meta(model).descs.relatedTypes._cacheable; + Ember.meta(model).descs.relatedTypes._cacheable = true; + Ember.testing = false; + try { + equal(get(model, 'relatedTypes'), get(model, 'relatedTypes'), 'relatedTypes are cached'); + equal(get(model, 'relatedTypes'), get(model, 'relatedTypes'), 'relatedTypes are cached'); + } finally { + Ember.testing = oldTesting; + Ember.meta(model).descs.relatedTypes._cacheable = oldCacheable; + } +}); + +test("relationships is cached in production", function() { + var model = store.modelFor('user'); + var oldTesting = Ember.testing; + //We set the cacheable to true because that is the default state for any CP and then assert that it + //did not get dynamically changed when accessed + var oldCacheable = Ember.meta(model).descs.relatedTypes._cacheable; + Ember.meta(model).descs.relationships._cacheable = true; + Ember.testing = false; + try { + equal(get(model, 'relationships'), get(model, 'relationships'), 'relationships are cached'); + equal(get(model, 'relationships'), get(model, 'relationships'), 'relationships are cached'); + } finally { + Ember.testing = oldTesting; + Ember.meta(model).descs.relationships._cacheable = oldCacheable; + } +}); + +test("relationship changes shouldn’t cause async fetches", function() { expect(2); /* Scenario: