Skip to content

Commit

Permalink
refactor modelFor/modelFactoryFor lookup to its own module
Browse files Browse the repository at this point in the history
This allows us to not have to pass the `store` around when looking up
inverse relationships. This is safe to do because the container should
always only have one factory class per model, and the factory classes
share the same container, even when there are multiple stores.
  • Loading branch information
Stanley Stuart committed May 28, 2015
1 parent ee2df66 commit 2d0af4c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 66 deletions.
13 changes: 9 additions & 4 deletions packages/ember-data/lib/system/relationships/ext.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import {
typeForRelationshipMeta,
relationshipFromMeta
} from "ember-data/system/relationship-meta";

import {
modelFor
} from 'ember-data/system/store/factory-locators';

import Model from "ember-data/system/model";
import {
Map,
Expand Down Expand Up @@ -178,9 +183,9 @@ Model.reopenClass({
@param {store} store an instance of DS.Store
@return {subclass of DS.Model} the type of the relationship, or undefined
*/
typeForRelationship: function(name, store) {
typeForRelationship: function(name) {
var relationship = get(this, 'relationshipsByName').get(name);
return relationship && store.modelFor(relationship.type);
return relationship && modelFor(this.__container__, relationship.type);
},

inverseMap: Ember.computed(function() {
Expand Down Expand Up @@ -224,7 +229,7 @@ Model.reopenClass({
//Calculate the inverse, ignoring the cache
_findInverseFor: function(name, store) {

var inverseType = this.typeForRelationship(name, store);
var inverseType = this.typeForRelationship(name);
if (!inverseType) {
return null;
}
Expand Down Expand Up @@ -618,7 +623,7 @@ Model.reopen({
},

inverseFor: function(key) {
return this.constructor.inverseFor(key, this.store);
return this.constructor.inverseFor(key);
}

});
68 changes: 6 additions & 62 deletions packages/ember-data/lib/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
*/

import normalizeModelName from "ember-data/system/normalize-model-name";
import {
modelFor,
modelFactoryFor
} from 'ember-data/system/store/factory-locators';
import {
InvalidError,
Adapter
Expand Down Expand Up @@ -1428,39 +1432,6 @@ Store = Service.extend({
return record;
},

/*
In case someone defined a relationship to a mixin, for example:
```
var Comment = DS.Model.extend({
owner: belongsTo('commentable'. { polymorphic: true})
});
var Commentable = Ember.Mixin.create({
comments: hasMany('comment')
});
```
we want to look up a Commentable class which has all the necessary
relationship metadata. Thus, we look up the mixin and create a mock
DS.Model, so we can access the relationship CPs of the mixin (`comments`)
in this case
*/

_modelForMixin: function(modelName) {
var normalizedModelName = normalizeModelName(modelName);
var registry = this.container._registry ? this.container._registry : this.container;
var mixin = registry.resolve('mixin:' + normalizedModelName);
if (mixin) {
//Cache the class as a model
registry.register('model:' + normalizedModelName, DS.Model.extend(mixin));
}
var factory = this.modelFactoryFor(normalizedModelName);
if (factory) {
factory.__isMixin = true;
factory.__mixin = mixin;
}

return factory;
},

/**
Returns a model class for a particular key. Used by
methods that take a type key (like `find`, `createRecord`,
Expand All @@ -1472,39 +1443,12 @@ Store = Service.extend({
*/
modelFor: function(modelName) {
Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of '+ Ember.inspect(modelName), typeof modelName === 'string');

var factory = this.modelFactoryFor(modelName);
if (!factory) {
//Support looking up mixins as base types for polymorphic relationships
factory = this._modelForMixin(modelName);
}
if (!factory) {
throw new Ember.Error("No model was found for '" + modelName + "'");
}
factory.modelName = factory.modelName || normalizeModelName(modelName);

// deprecate typeKey
if (!('typeKey' in factory)) {
Ember.defineProperty(factory, 'typeKey', {
enumerable: true,
configurable: false,
get: function() {
Ember.deprecate('Usage of `typeKey` has been deprecated and will be removed in Ember Data 1.0. It has been replaced by `modelName` on the model class.');
return Ember.String.camelize(this.modelName);
},
set: function() {
Ember.assert('Setting typeKey is not supported. In addition, typeKey has also been deprecated in favor of modelName. Setting modelName is also not supported.');
}
});
}

return factory;
return modelFor(this.container, modelName);
},

modelFactoryFor: function(modelName) {
Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of '+ Ember.inspect(modelName), typeof modelName === 'string');
var normalizedKey = normalizeModelName(modelName);
return this.container.lookupFactory('model:' + normalizedKey);
return modelFactoryFor(this.container, modelName);
},

/**
Expand Down
74 changes: 74 additions & 0 deletions packages/ember-data/lib/system/store/factory-locators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import normalizeModelName from 'ember-data/system/normalize-model-name';

function modelFor(container, modelName) {
var factory = modelFactoryFor(container, modelName);

if (!factory) {
//Support looking up mixins as base types for polymorphic relationships
factory = modelForMixin(container, modelName);
}
if (!factory) {
throw new Ember.Error("No model was found for '" + modelName + "'");
}
factory.modelName = factory.modelName || normalizeModelName(modelName);
factory.__container__ = factory.__container__ || container;

// deprecate typeKey
if (!('typeKey' in factory)) {
Ember.defineProperty(factory, 'typeKey', {
enumerable: true,
configurable: false,
get: function() {
Ember.deprecate('Usage of `typeKey` has been deprecated and will be removed in Ember Data 1.0. It has been replaced by `modelName` on the model class.');
return Ember.String.camelize(this.modelName);
},
set: function() {
Ember.assert('Setting typeKey is not supported. In addition, typeKey has also been deprecated in favor of modelName. Setting modelName is also not supported.');
}
});
}

return factory;
}

function modelFactoryFor(container, modelName) {
var normalizedKey = normalizeModelName(modelName);
return container.lookupFactory('model:' + normalizedKey);
}

/*
In case someone defined a relationship to a mixin, for example:
```
var Comment = DS.Model.extend({
owner: belongsTo('commentable'. { polymorphic: true})
});
var Commentable = Ember.Mixin.create({
comments: hasMany('comment')
});
```
we want to look up a Commentable class which has all the necessary
relationship metadata. Thus, we look up the mixin and create a mock
DS.Model, so we can access the relationship CPs of the mixin (`comments`)
in this case
*/
function modelForMixin(container, modelName) {
var normalizedModelName = normalizeModelName(modelName);
var registry = container._registry ? container._registry : container;
var mixin = registry.resolve('mixin:' + normalizedModelName);
if (mixin) {
//Cache the class as a model
registry.register('model:' + normalizedModelName, DS.Model.extend(mixin));
}
var factory = modelFactoryFor(container, normalizedModelName);
if (factory) {
factory.__isMixin = true;
factory.__mixin = mixin;
}

return factory;
}

export {
modelFor,
modelFactoryFor
};

0 comments on commit 2d0af4c

Please sign in to comment.