Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use public API for container/registry when possible. #3912

Merged
merged 1 commit into from
Nov 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/ember-data/lib/serializers/json-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import coerceId from "ember-data/system/coerce-id";
import normalizeModelName from "ember-data/system/normalize-model-name";
import { modelHasAttributeOrRelationshipNamedType } from "ember-data/utils";

import {
getOwner
} from 'ember-data/utils';

import { errorsArrayToHash } from "ember-data/adapters/errors";

var get = Ember.get;
Expand Down Expand Up @@ -1366,8 +1370,10 @@ export default Serializer.extend({
@return {DS.Transform} transform
*/
transformFor: function(attributeType, skipAssertion) {
var transform = this.container.lookup('transform:' + attributeType);
var transform = getOwner(this).lookup('transform:' + attributeType);

Ember.assert("Unable to find transform for '" + attributeType + "'", skipAssertion || !!transform);

return transform;
}
});
23 changes: 18 additions & 5 deletions packages/ember-data/lib/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import Relationships from "ember-data/system/relationships/state/create";
import Snapshot from "ember-data/system/snapshot";
import EmptyObject from "ember-data/system/empty-object";

import {
getOwner
} from 'ember-data/utils';

var Promise = Ember.RSVP.Promise;
var get = Ember.get;
var set = Ember.set;
Expand Down Expand Up @@ -46,11 +50,10 @@ var guid = 0;
@class InternalModel
*/

export default function InternalModel(type, id, store, container, data) {
export default function InternalModel(type, id, store, _, data) {
this.type = type;
this.id = id;
this.store = store;
this.container = container;
this._data = data || new EmptyObject();
this.modelName = type.modelName;
this.dataHasInitialized = false;
Expand Down Expand Up @@ -110,17 +113,27 @@ InternalModel.prototype = {
constructor: InternalModel,
materializeRecord: function() {
Ember.assert("Materialized " + this.modelName + " record with id:" + this.id + "more than once", this.record === null || this.record === undefined);

// lookupFactory should really return an object that creates
// instances with the injections applied
this.record = this.type._create({
var createOptions = {
store: this.store,
container: this.container,
_internalModel: this,
id: this.id,
currentState: get(this, 'currentState'),
isError: this.isError,
adapterError: this.error
});
};

if (Ember.setOwner) {
// ensure that `Ember.getOwner(this)` works inside a model instance
Ember.setOwner(createOptions, getOwner(this.store));
} else {
createOptions.container = this.store.container;
}

this.record = this.type._create(createOptions);

this._triggerDeferredTriggers();
},

Expand Down
19 changes: 19 additions & 0 deletions packages/ember-data/lib/system/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -843,4 +843,23 @@ Model.reopenClass({
modelName: null
});

// if `Ember.setOwner` is defined, accessing `this.container` is
// deprecated (but functional). In "standard" Ember usage, this
// deprecation is actually created via an `.extend` of the factory
// inside the container itself, but that only happens on models
// with MODEL_FACTORY_INJECTIONS enabled :(
if (Ember.setOwner) {
Object.defineProperty(Model.prototype, 'container', {
configurable: true,
enumerable: false,
get() {
Ember.deprecate('Using the injected `container` is deprecated. Please use the `getOwner` helper instead to access the owner of this object.',
false,
{ id: 'ember-application.injected-container', until: '3.0.0' });

return this.store.container;
}
});
}

export default Model;
22 changes: 15 additions & 7 deletions packages/ember-data/lib/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ import {
_queryRecord
} from "ember-data/system/store/finders";

import {
getOwner
} from 'ember-data/utils';

import coerceId from "ember-data/system/coerce-id";

import RecordArrayManager from "ember-data/system/record-array-manager";
Expand Down Expand Up @@ -220,7 +224,7 @@ Store = Service.extend({
store: this
});
this._pendingSave = [];
this._instanceCache = new ContainerInstanceCache(this.container);
this._instanceCache = new ContainerInstanceCache(getOwner(this));
//Used to keep track of all the find requests that need to be coalesced
this._pendingFetch = Map.create();
},
Expand Down Expand Up @@ -1475,11 +1479,12 @@ Store = Service.extend({
// container.registry = 2.1
// container._registry = 1.11 - 2.0
// container = < 1.11
var registry = this.container.registry || this.container._registry || this.container;
var mixin = this.container.lookupFactory('mixin:' + normalizedModelName);
var owner = getOwner(this);

var mixin = owner._lookupFactory('mixin:' + normalizedModelName);
if (mixin) {
//Cache the class as a model
registry.register('model:' + normalizedModelName, DS.Model.extend(mixin));
owner.register('model:' + normalizedModelName, DS.Model.extend(mixin));
}
var factory = this.modelFactoryFor(normalizedModelName);
if (factory) {
Expand Down Expand Up @@ -1518,7 +1523,10 @@ Store = Service.extend({
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);

var owner = getOwner(this);

return owner._lookupFactory('model:' + normalizedKey);
},

/**
Expand Down Expand Up @@ -1701,7 +1709,7 @@ Store = Service.extend({
},

_hasModelFor: function(type) {
return this.container.lookupFactory(`model:${type}`);
return getOwner(this)._lookupFactory(`model:${type}`);
},

_pushInternalModel: function(data) {
Expand Down Expand Up @@ -1867,7 +1875,7 @@ Store = Service.extend({

// lookupFactory should really return an object that creates
// instances with the injections applied
var internalModel = new InternalModel(type, id, this, this.container, data);
var internalModel = new InternalModel(type, id, this, null, data);

// if we're creating an item, this process will be done
// later, once the object has been persisted.
Expand Down
10 changes: 5 additions & 5 deletions packages/ember-data/lib/system/store/container-instance-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import EmptyObject from "ember-data/system/empty-object";
* @class ContainerInstanceCache
*
*/
export default function ContainerInstanceCache(container) {
this._container = container;
this._cache = new EmptyObject();
export default function ContainerInstanceCache(owner) {
this._owner = owner;
this._cache = new EmptyObject();
}

ContainerInstanceCache.prototype = new EmptyObject();
Expand Down Expand Up @@ -55,7 +55,7 @@ Ember.merge(ContainerInstanceCache.prototype, {
instanceFor: function(key) {
let cache = this._cache;
if (!cache[key]) {
let instance = this._container.lookup(key);
let instance = this._owner.lookup(key);
if (instance) {
cache[key] = instance;
}
Expand All @@ -74,7 +74,7 @@ Ember.merge(ContainerInstanceCache.prototype, {
cacheEntry.destroy();
}
}
this._container = null;
this._owner = null;
},

constructor: ContainerInstanceCache,
Expand Down
32 changes: 31 additions & 1 deletion packages/ember-data/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,37 @@ function modelHasAttributeOrRelationshipNamedType(modelClass) {
return get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type');
}

/*
ember-container-inject-owner is a new feature in Ember 2.3 that finally provides a public
API for looking items up. This function serves as a super simple polyfill to avoid
triggering deprecations.
*/
function getOwner(context) {
var owner;

if (Ember.getOwner) {
owner = Ember.getOwner(context);
}

if (!owner && context.container) {
owner = context.container;
}

if (owner && owner.lookupFactory && !owner._lookupFactory) {
// `owner` is a container, we are just making this work
owner._lookupFactory = owner.lookupFactory;
owner.register = function() {
var registry = owner.registry || owner._registry || owner;

return registry.register(...arguments);
};
}

return owner;
}

export {
assertPolymorphicType,
modelHasAttributeOrRelationshipNamedType
modelHasAttributeOrRelationshipNamedType,
getOwner
};
14 changes: 7 additions & 7 deletions packages/ember-data/tests/unit/model/internal-model-test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
module("unit/model/internal-model - Internal Model");

var mockModelFactory = {
_create: function() {
return { trigger: function() {} };
},
function MockModelFactory () { }

eachRelationship: function() {
}
MockModelFactory._create = function() {
return { trigger: function() {} };
};

MockModelFactory.eachRelationship = function() { };

test("Materializing a model twice errors out", function() {
expect(1);
var internalModel = new DS.InternalModel(mockModelFactory, null, null, null);
var internalModel = new DS.InternalModel(MockModelFactory, null, { }, null);

internalModel.materializeRecord();
expectAssertion(function() {
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-data/tests/unit/store/model-for-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module("unit/store/model_for - DS.Store#modelFor", {
"blog.post": DS.Model.extend()
});
store = env.store;
container = store.container;
container = env.container;
registry = env.registry;
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module("unit/store/serializer_for - DS.Store#serializerFor", {
Person = DS.Model.extend({});
var env = setupStore({ person: Person });
store = env.store;
container = store.container;
container = env.container;
registry = env.registry;
},

Expand Down
26 changes: 24 additions & 2 deletions tests/ember-configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
ENV['ENABLE_OPTIONAL_FEATURES'] = !!QUnit.urlParams.enableoptionalfeatures;
ENV['RAISE_ON_DEPRECATION'] = true;

var Owner;

window.async = function(callback, timeout) {
var timer;
stop();
Expand Down Expand Up @@ -52,13 +54,33 @@
};

window.setupStore = function(options) {
var container, registry;
var container, registry, owner;
var env = {};
options = options || {};

// This is done once upon first setupStore call (we cannot do it eagerly
// because this file is loaded before Ember itself).
if (!Owner) {
if (Ember._RegistryProxyMixin && Ember._ContainerProxyMixin) {
Owner = Ember.Object.extend(Ember._RegistryProxyMixin, Ember._ContainerProxyMixin);
} else {
Owner = Ember.Object.extend();
}
}

if (Ember.Registry) {

registry = env.registry = new Ember.Registry();
container = env.container = registry.container();

owner = Owner.create({
__registry__: registry
});

container = env.container = registry.container({
owner: owner
});

owner.__container__ = container;
} else {
container = env.container = new Ember.Container();
registry = env.registry = container;
Expand Down