From b8963292e5285526a7d6fb5101f2184951454773 Mon Sep 17 00:00:00 2001 From: Artem Charykov Date: Sun, 26 Apr 2015 21:36:58 +0400 Subject: [PATCH] [BUGFIX] Patch ActiveModelSerializer for properly serializing and extracting namespaced model names in polymorphic type attributes. Now AMS accepts '::' istead of '/'. Fixes #3019. --- CHANGELOG.md | 2 + .../lib/system/active-model-serializer.js | 11 +- ...el-serializer-namespaced-modelname-test.js | 118 ++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 packages/activemodel-adapter/tests/integration/active-model-serializer-namespaced-modelname-test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a028346a61..0c489e76b29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Master + * Fix ActiveModelSerializer polymorphic type processing for namespaced model names. Now AMS accepts '::' instead of '/'. + ### Release 1.0.0-beta.16.1 (March 24, 2015) * Use ember-inflector 1.5 diff --git a/packages/activemodel-adapter/lib/system/active-model-serializer.js b/packages/activemodel-adapter/lib/system/active-model-serializer.js index c4c14b84366..c29f1b05bc1 100644 --- a/packages/activemodel-adapter/lib/system/active-model-serializer.js +++ b/packages/activemodel-adapter/lib/system/active-model-serializer.js @@ -6,7 +6,7 @@ import RESTSerializer from "ember-data/serializers/rest-serializer"; var forEach = Ember.EnumerableUtils.forEach; var camelize = Ember.String.camelize; -var capitalize = Ember.String.capitalize; +var classify = Ember.String.classify; var decamelize = Ember.String.decamelize; var underscore = Ember.String.underscore; @@ -166,7 +166,9 @@ var ActiveModelSerializer = RESTSerializer.extend({ if (Ember.isNone(belongsTo)) { json[jsonKey] = null; } else { - json[jsonKey] = capitalize(camelize(belongsTo.typeKey)); + json[jsonKey] = classify(belongsTo.typeKey).replace(/(\/)([a-z])/g, function(match, separator, chr) { + return match.toUpperCase(); + }).replace('/', '::'); } }, @@ -285,6 +287,11 @@ var ActiveModelSerializer = RESTSerializer.extend({ } }, this); } + }, + typeForRoot: function(key) { + return camelize(singularize(key)).replace(/(^|\:)([A-Z])/g, function(match, separator, chr) { + return match.toLowerCase(); + }).replace('::', '/'); } }); diff --git a/packages/activemodel-adapter/tests/integration/active-model-serializer-namespaced-modelname-test.js b/packages/activemodel-adapter/tests/integration/active-model-serializer-namespaced-modelname-test.js new file mode 100644 index 00000000000..e90491f84c5 --- /dev/null +++ b/packages/activemodel-adapter/tests/integration/active-model-serializer-namespaced-modelname-test.js @@ -0,0 +1,118 @@ +var SuperVillain, EvilMinion, YellowMinion, DoomsdayDevice, MediocreVillain, env; +var run = Ember.run; + +module("integration/active_model - AMS-namespaced-model-names", { + setup: function() { + SuperVillain = DS.Model.extend({ + firstName: DS.attr('string'), + lastName: DS.attr('string'), + evilMinions: DS.hasMany("evilMinion") + }); + + EvilMinion = DS.Model.extend({ + superVillain: DS.belongsTo('superVillain'), + name: DS.attr('string') + }); + YellowMinion = EvilMinion.extend(); + DoomsdayDevice = DS.Model.extend({ + name: DS.attr('string'), + evilMinion: DS.belongsTo('evilMinion', { polymorphic: true }) + }); + MediocreVillain = DS.Model.extend({ + name: DS.attr('string'), + evilMinions: DS.hasMany('evilMinion', { polymorphic: true }) + }); + env = setupStore({ + superVillain: SuperVillain, + evilMinion: EvilMinion, + 'evilMinions/yellowMinion': YellowMinion, + doomsdayDevice: DoomsdayDevice, + mediocreVillain: MediocreVillain + }); + env.store.modelFor('superVillain'); + env.store.modelFor('evilMinion'); + env.store.modelFor('evilMinions/yellowMinion'); + env.store.modelFor('doomsdayDevice'); + env.store.modelFor('mediocreVillain'); + env.registry.register('serializer:application', DS.ActiveModelSerializer); + env.registry.register('serializer:-active-model', DS.ActiveModelSerializer); + env.registry.register('adapter:-active-model', DS.ActiveModelAdapter); + env.amsSerializer = env.container.lookup("serializer:-active-model"); + env.amsAdapter = env.container.lookup("adapter:-active-model"); + }, + + teardown: function() { + run(env.store, 'destroy'); + } +}); + +test("serialize polymorphic", function() { + var tom, ray; + run(function() { + tom = env.store.createRecord('evilMinions/yellowMinion', { name: "Alex", id: "124" }); + ray = env.store.createRecord(DoomsdayDevice, { evilMinion: tom, name: "DeathRay" }); + }); + + var json = env.amsSerializer.serialize(ray._createSnapshot()); + + deepEqual(json, { + name: "DeathRay", + evil_minion_type: "EvilMinions::YellowMinion", + evil_minion_id: "124" + }); +}); + +test("serialize polymorphic when type key is not camelized", function() { + YellowMinion.typeKey = 'evil-minions/yellow-minion'; + var tom, ray; + run(function() { + tom = env.store.createRecord(YellowMinion, { name: "Alex", id: "124" }); + ray = env.store.createRecord(DoomsdayDevice, { evilMinion: tom, name: "DeathRay" }); + }); + + var json = env.amsSerializer.serialize(ray._createSnapshot()); + + deepEqual(json["evil_minion_type"], "EvilMinions::YellowMinion"); +}); + +test("extractPolymorphic hasMany", function() { + var json_hash = { + mediocre_villain: { id: 1, name: "Dr Horrible", evil_minions: [{ type: "EvilMinions::YellowMinion", id: 12 }] }, + evil_minions: [{ id: 12, name: "Alex", doomsday_device_ids: [1] }] + }; + var json; + + run(function() { + json = env.amsSerializer.extractSingle(env.store, MediocreVillain, json_hash); + }); + + deepEqual(json, { + "id": 1, + "name": "Dr Horrible", + "evilMinions": [{ + type: "evilMinions/yellowMinion", + id: 12 + }] + }); +}); + +test("extractPolymorphic", function() { + var json_hash = { + doomsday_device: { id: 1, name: "DeathRay", evil_minion: { type: "EvilMinions::YellowMinion", id: 12 } }, + evil_minions: [{ id: 12, name: "Alex", doomsday_device_ids: [1] }] + }; + var json; + + run(function() { + json = env.amsSerializer.extractSingle(env.store, DoomsdayDevice, json_hash); + }); + + deepEqual(json, { + "id": 1, + "name": "DeathRay", + "evilMinion": { + type: "evilMinions/yellowMinion", + id: 12 + } + }); +});