From d7b1e63f97ac042d311d292e1d28c7c1246fbfb8 Mon Sep 17 00:00:00 2001 From: pangratz Date: Sat, 10 Oct 2015 16:27:09 +0200 Subject: [PATCH] [BUGFIX beta] Consider embedded record having attr/rel named type --- .../lib/serializers/json-serializer.js | 5 +- .../lib/serializers/rest-serializer.js | 4 +- packages/ember-data/lib/utils.js | 15 +++- .../serializers/json-serializer-test.js | 76 +++++++++++++++++++ packages/ember-data/tests/unit/utils-test.js | 20 +++++ 5 files changed, 116 insertions(+), 4 deletions(-) diff --git a/packages/ember-data/lib/serializers/json-serializer.js b/packages/ember-data/lib/serializers/json-serializer.js index fdf27078f73..a550f2ec61b 100644 --- a/packages/ember-data/lib/serializers/json-serializer.js +++ b/packages/ember-data/lib/serializers/json-serializer.js @@ -1,6 +1,7 @@ import Serializer from "ember-data/system/serializer"; import coerceId from "ember-data/system/coerce-id"; import normalizeModelName from "ember-data/system/normalize-model-name"; +import { modelHasAttributeOrRelationshipNamedType } from "ember-data/utils"; import { errorsArrayToHash } from "ember-data/adapters/errors"; @@ -574,7 +575,9 @@ export default Serializer.extend({ if (relationshipHash.id) { relationshipHash.id = coerceId(relationshipHash.id); } - if (relationshipHash.type) { + + const modelClass = this.store.modelFor(relationshipModelName); + if (relationshipHash.type && !modelHasAttributeOrRelationshipNamedType(modelClass)) { relationshipHash.type = this.modelNameFromPayloadKey(relationshipHash.type); } return relationshipHash; diff --git a/packages/ember-data/lib/serializers/rest-serializer.js b/packages/ember-data/lib/serializers/rest-serializer.js index 17ceff90a3f..2d26d7c8e0f 100644 --- a/packages/ember-data/lib/serializers/rest-serializer.js +++ b/packages/ember-data/lib/serializers/rest-serializer.js @@ -6,9 +6,9 @@ import JSONSerializer from "ember-data/serializers/json-serializer"; import normalizeModelName from "ember-data/system/normalize-model-name"; import {singularize} from "ember-inflector/lib/system/string"; import coerceId from "ember-data/system/coerce-id"; +import { modelHasAttributeOrRelationshipNamedType } from "ember-data/utils"; var camelize = Ember.String.camelize; -var get = Ember.get; /** Normally, applications will use the `RESTSerializer` by implementing @@ -149,7 +149,7 @@ var RESTSerializer = JSONSerializer.extend({ let modelClass = store.modelFor(modelName); let serializer = store.serializerFor(modelName); - const primaryHasTypeAttribute = get(modelClass, 'attributes').get('type') || get(modelClass, 'relationshipsByName').get('type'); + const primaryHasTypeAttribute = modelHasAttributeOrRelationshipNamedType(modelClass); /*jshint loopfunc:true*/ arrayHash.forEach((hash) => { let { data, included } = this._normalizePolymorphicRecord(store, hash, prop, modelClass, serializer, primaryHasTypeAttribute); diff --git a/packages/ember-data/lib/utils.js b/packages/ember-data/lib/utils.js index 103160c2b7f..b31e9262d10 100644 --- a/packages/ember-data/lib/utils.js +++ b/packages/ember-data/lib/utils.js @@ -1,5 +1,7 @@ import Ember from 'ember'; +const get = Ember.get; + /** Assert that `addedRecord` has a valid type so it can be added to the relationship of the `record`. @@ -42,6 +44,17 @@ function checkPolymorphic(typeClass, addedRecord) { return typeClass.detect(addedRecord.type); } +/** + Check if the passed model has a `type` attribute or a relationship named `type`. + + @method modelHasAttributeOrRelationshipNamedType + @param modelClass + */ +function modelHasAttributeOrRelationshipNamedType(modelClass) { + return get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type'); +} + export { - assertPolymorphicType + assertPolymorphicType, + modelHasAttributeOrRelationshipNamedType }; diff --git a/packages/ember-data/tests/integration/serializers/json-serializer-test.js b/packages/ember-data/tests/integration/serializers/json-serializer-test.js index 691aed1a774..67767cc3e91 100644 --- a/packages/ember-data/tests/integration/serializers/json-serializer-test.js +++ b/packages/ember-data/tests/integration/serializers/json-serializer-test.js @@ -319,6 +319,82 @@ test('Serializer should respect the attrs hash when serializing records', functi equal(payload.my_parent, '2'); }); +test('Serializer respects if embedded model has an attribute named "type" - #3726', function() { + env.registry.register("serializer:parent", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + child: { embedded: 'always' } + } + })); + env.registry.register("model:parent", DS.Model.extend({ + child: DS.belongsTo('child') + })); + env.registry.register("model:child", DS.Model.extend({ + type: DS.attr() + })); + + var jsonHash = { + id: 1, + child: { + id: 1, + type: 'first_type' + } + }; + + var Parent = env.store.modelFor('parent'); + var payload = env.store.serializerFor('parent').normalizeResponse(env.store, Parent, jsonHash, '1', 'findRecord'); + deepEqual(payload.included, [ + { + id: '1', + type: 'child', + attributes: { + type: 'first_type' + }, + relationships: {} + } + ]); +}); + +test('Serializer respects if embedded model has a relationship named "type" - #3726', function() { + env.registry.register("serializer:parent", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + child: { embedded: 'always' } + } + })); + env.registry.register("model:parent", DS.Model.extend({ + child: DS.belongsTo('child') + })); + env.registry.register("model:child", DS.Model.extend({ + type: DS.belongsTo('le-type') + })); + env.registry.register("model:le-type", DS.Model.extend()); + + var jsonHash = { + id: 1, + child: { + id: 1, + type: "my_type_id" + } + }; + + var Parent = env.store.modelFor('parent'); + var payload = env.store.serializerFor('parent').normalizeResponse(env.store, Parent, jsonHash, '1', 'findRecord'); + deepEqual(payload.included, [ + { + id: '1', + type: 'child', + attributes: {}, + relationships: { + type: { + data: { + id: 'my_type_id', + type: 'le-type' + } + } + } + } + ]); +}); + test('Serializer respects `serialize: false` on the attrs hash', function() { expect(2); env.registry.register("serializer:post", DS.JSONSerializer.extend({ diff --git a/packages/ember-data/tests/unit/utils-test.js b/packages/ember-data/tests/unit/utils-test.js index 8e9546ba64b..94053ba4801 100644 --- a/packages/ember-data/tests/unit/utils-test.js +++ b/packages/ember-data/tests/unit/utils-test.js @@ -1,5 +1,6 @@ // TODO enable import once this is possible // import { assertPolymorphicType } from "ember-data/utils"; +// import { modelHasAttributeOrRelationshipNamedType } from "ember-data/utils"; var env, User, Message, Post, Person, Video, Medium; @@ -135,3 +136,22 @@ test("assertPolymorphicType works for mixins", function() { // assertPolymorphicType(post, relationship, person); }, "You cannot add a record of type 'person' to the 'post.medias' relationship (only 'medium' allowed)"); }); + +// TODO enable once we can `import x from y;` in tests +// test("modelHasAttributeOrRelationshipNamedType", function() { +// var ModelWithTypeAttribute = DS.Model.extend({ +// type: DS.attr() +// }); +// var ModelWithTypeBelongsTo = DS.Model.extend({ +// type: DS.belongsTo() +// }); +// var ModelWithTypeHasMany = DS.Model.extend({ +// type: DS.hasMany() +// }); +// +// equal(modelHasAttributeOrRelationshipNamedType(DS.Model), false); +// +// equal(modelHasAttributeOrRelationshipNamedType(ModelWithTypeAttribute), true); +// equal(modelHasAttributeOrRelationshipNamedType(ModelWithTypeBelongsTo), true); +// equal(modelHasAttributeOrRelationshipNamedType(ModelWithTypeHasMany), true); +// });