Skip to content

Commit

Permalink
use dasherized model names everywhere
Browse files Browse the repository at this point in the history
Previously, we allowed container keys to be loosy-goosy and normalized
them in several places. This commit consolidates those efforts into
one place `normalizeTypeKey`.
  • Loading branch information
Stanley Stuart committed May 10, 2015
1 parent 4b44728 commit c6de197
Show file tree
Hide file tree
Showing 18 changed files with 319 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,10 @@ var ActiveModelSerializer = RESTSerializer.extend({
}
},
typeForRoot: function(key) {
return camelize(singularize(key)).replace(/(^|\:)([A-Z])/g, function(match, separator, chr) {
var normalized = camelize(singularize(key)).replace(/(^|\:)([A-Z])/g, function(match, separator, chr) {
return match.toLowerCase();
}).replace('::', '/');
return this._super(normalized);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ test("extractPolymorphic hasMany", function() {
"id": 1,
"name": "Dr Horrible",
"evilMinions": [{
type: "evilMinions/yellowMinion",
type: "evil-minions/yellow-minion",
id: 12
}]
});
Expand All @@ -111,7 +111,7 @@ test("extractPolymorphic", function() {
"id": 1,
"name": "DeathRay",
"evilMinion": {
type: "evilMinions/yellowMinion",
type: "evil-minions/yellow-minion",
id: 12
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ test("extractPolymorphic hasMany", function() {
"id": 1,
"name": "Dr Horrible",
"evilMinions": [{
type: "yellowMinion",
type: "yellow-minion",
id: 12
}]
});
Expand All @@ -271,7 +271,7 @@ test("extractPolymorphic", function() {
"id": 1,
"name": "DeathRay",
"evilMinion": {
type: "yellowMinion",
type: "yellow-minion",
id: 12
}
});
Expand Down
12 changes: 6 additions & 6 deletions packages/ember-data/lib/serializers/rest-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
*/

import JSONSerializer from "ember-data/serializers/json-serializer";
import normalizeTypeKey from "ember-data/system/normalize-type-key";

var forEach = Ember.ArrayPolyfills.forEach;
var map = Ember.ArrayPolyfills.map;
var camelize = Ember.String.camelize;

import { singularize } from "ember-inflector/lib/system/string";

function coerceId(id) {
return id == null ? null : id + '';
}
Expand Down Expand Up @@ -509,8 +508,8 @@ var RESTSerializer = JSONSerializer.extend({
This method is used to convert each JSON root key in the payload
into a typeKey that it can use to look up the appropriate model for
that part of the payload. By default the typeKey for a model is its
name in camelCase, so if your JSON root key is 'fast-car' you would
use typeForRoot to convert it to 'fastCar' so that Ember Data finds
name in camelCase, so if your JSON root key is 'fast_car' you would
use typeForRoot to convert it to 'fast-car' so that Ember Data finds
the `FastCar` model.
If you diverge from this norm you should also consider changes to
Expand Down Expand Up @@ -549,7 +548,7 @@ var RESTSerializer = JSONSerializer.extend({
@return {String} the model's typeKey
*/
typeForRoot: function(key) {
return camelize(singularize(key));
return normalizeTypeKey(key);
},

// SERIALIZE
Expand Down Expand Up @@ -724,7 +723,8 @@ var RESTSerializer = JSONSerializer.extend({
@param {Object} options
*/
serializeIntoHash: function(hash, typeClass, snapshot, options) {
hash[typeClass.typeKey] = this.serialize(snapshot, options);
var rootTypeKey = camelize(typeClass.typeKey);
hash[rootTypeKey] = this.serialize(snapshot, options);
},

/**
Expand Down
16 changes: 16 additions & 0 deletions packages/ember-data/lib/system/normalize-type-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {singularize} from 'ember-inflector/lib/system/string';

var dasherize = Ember.String.dasherize;
var camelize = Ember.String.camelize;

/**
All typeKeys are dasherized internally. Changing this function may
require changes to other normalization hooks (such as typeForRoot).
@method normalizeTypeKey
@private
@param {String} type
@return {String} if the adapter can generate one, an ID
*/
export default function normalizeTypeKey(typeKey) {
return singularize(dasherize(camelize(typeKey)));
}
4 changes: 2 additions & 2 deletions packages/ember-data/lib/system/relationship-meta.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { singularize } from "ember-inflector/lib/system";
import normalizeTypeKey from "ember-data/system/normalize-type-key";

export function typeForRelationshipMeta(store, meta) {
var typeKey, typeClass;

typeKey = meta.type || meta.key;
if (typeof typeKey === 'string') {
if (meta.kind === 'hasMany') {
typeKey = singularize(typeKey);
typeKey = normalizeTypeKey(typeKey);
}
typeClass = store.modelFor(typeKey);
} else {
Expand Down
27 changes: 18 additions & 9 deletions packages/ember-data/lib/system/relationships/belongs-to.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Model from 'ember-data/system/model';

import computedPolyfill from "ember-data/utils/computed-polyfill";
import normalizeTypeKey from "ember-data/system/normalize-type-key";

/**
`DS.belongsTo` is used to define One-To-One and One-To-Many
Expand Down Expand Up @@ -56,24 +57,32 @@ import computedPolyfill from "ember-data/utils/computed-polyfill";
@namespace
@method belongsTo
@for DS
@param {String} type (optional) type of the relationship
@param {String} modelTypeKey (optional) type of the relationship
@param {Object} options (optional) a hash of options
@return {Ember.computed} relationship
*/
function belongsTo(type, options) {
if (typeof type === 'object') {
options = type;
type = undefined;
function belongsTo(modelTypeKey, options) {
var opts, typeKey;
if (typeof modelTypeKey === 'object') {
opts = modelTypeKey;
typeKey = undefined;
} else {
opts = options;
typeKey = modelTypeKey;
}

Ember.assert("The first argument to DS.belongsTo must be a string representing a model type key, not an instance of " + Ember.inspect(type) + ". E.g., to define a relation to the Person model, use DS.belongsTo('person')", typeof type === 'string' || typeof type === 'undefined');
if (typeof typeKey === 'string') {
typeKey = normalizeTypeKey(typeKey);
}

Ember.assert("The first argument to DS.belongsTo must be a string representing a model type key, not an instance of " + Ember.inspect(typeKey) + ". E.g., to define a relation to the Person model, use DS.belongsTo('person')", typeof typeKey === 'string' || typeof typeKey === 'undefined');

options = options || {};
opts = opts || {};

var meta = {
type: type,
type: typeKey,
isRelationship: true,
options: options,
options: opts,
kind: 'belongsTo',
key: null
};
Expand Down
5 changes: 5 additions & 0 deletions packages/ember-data/lib/system/relationships/has-many.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import Model from "ember-data/system/model";
import normalizeTypeKey from "ember-data/system/normalize-type-key";

/**
`DS.hasMany` is used to define One-To-Many and Many-To-Many
Expand Down Expand Up @@ -103,6 +104,10 @@ function hasMany(type, options) {

options = options || {};

if (typeof type === 'string') {
type = normalizeTypeKey(type);
}

// Metadata about relationships is stored on the meta of
// the relationship. This is used for introspection and
// serialization. Note that `key` is populated lazily
Expand Down
35 changes: 18 additions & 17 deletions packages/ember-data/lib/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
@module ember-data
*/

import normalizeTypeKey from "ember-data/system/normalize-type-key";
import {
InvalidError,
Adapter
} from "ember-data/system/adapter";
import { singularize } from "ember-inflector/lib/system/string";
import {
Map
} from "ember-data/system/map";
Expand Down Expand Up @@ -96,8 +96,6 @@ var Promise = Ember.RSVP.Promise;
var copy = Ember.copy;
var Store;

var camelize = Ember.String.camelize;

var Service = Ember.Service;
if (!Service) {
Service = Ember.Object;
Expand Down Expand Up @@ -1429,14 +1427,15 @@ Store = Service.extend({
in this case
*/

_modelForMixin: function(key) {
_modelForMixin: function(typeKey) {
var normalizedTypeKey = this._normalizeTypeKey(typeKey);
var registry = this.container._registry ? this.container._registry : this.container;
var mixin = registry.resolve('mixin:' + key);
var mixin = registry.resolve('mixin:' + normalizedTypeKey);
if (mixin) {
//Cache the class as a model
registry.register('model:' + key, DS.Model.extend(mixin));
registry.register('model:' + normalizedTypeKey, DS.Model.extend(mixin));
}
var factory = this.modelFactoryFor(key);
var factory = this.modelFactoryFor(normalizedTypeKey);
if (factory) {
factory.__isMixin = true;
factory.__mixin = mixin;
Expand Down Expand Up @@ -1480,7 +1479,8 @@ Store = Service.extend({
},

modelFactoryFor: function(key) {
return this.container.lookupFactory('model:' + key);
var normalizedKey = this._normalizeTypeKey(key);
return this.container.lookupFactory('model:' + normalizedKey);
},

/**
Expand Down Expand Up @@ -1545,16 +1545,16 @@ Store = Service.extend({
records, as well as to update existing records.
@method push
@param {String or subclass of DS.Model} type
@param {String or subclass of DS.Model} typeKey
@param {Object} data
@return {DS.Model} the record that was created or
updated.
*/
push: function(typeName, data) {
Ember.assert("Expected an object as `data` in a call to `push` for " + typeName + " , but was " + data, Ember.typeOf(data) === 'object');
Ember.assert("You must include an `id` for " + typeName + " in an object passed to `push`", data.id != null && data.id !== '');
push: function(typeKey, data) {
Ember.assert("Expected an object as `data` in a call to `push` for " + typeKey + " , but was " + data, Ember.typeOf(data) === 'object');
Ember.assert("You must include an `id` for " + typeKey + " in an object passed to `push`", data.id != null && data.id !== '');

var type = this.modelFor(typeName);
var type = this.modelFor(typeKey);
var filter = Ember.EnumerableUtils.filter;

// If Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS is set to true and the payload
Expand Down Expand Up @@ -1902,12 +1902,13 @@ Store = Service.extend({
@method retrieveManagedInstance
@private
@param {String} type the object type
@param {String} type the object typeKey
@param {String} type the object name
@return {Ember.Object}
*/
retrieveManagedInstance: function(type, name) {
var key = type+":"+name;
retrieveManagedInstance: function(typeKey, name) {
var normalizedTypeKey = this._normalizeTypeKey(typeKey);
var key = normalizedTypeKey + ":" +name;

if (!this._containerCache[key]) {
var instance = this.container.lookup(key);
Expand Down Expand Up @@ -1952,7 +1953,7 @@ Store = Service.extend({
@return {String} if the adapter can generate one, an ID
*/
_normalizeTypeKey: function(key) {
return camelize(singularize(key));
return normalizeTypeKey(key);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ test('buildURL - with camelized names', function() {
adapter.setProperties({
pathForType: function(type) {
var decamelized = Ember.String.decamelize(type);
return Ember.String.pluralize(decamelized);
return Ember.String.underscore(Ember.String.pluralize(decamelized));
}
});

Expand Down
Loading

0 comments on commit c6de197

Please sign in to comment.