diff --git a/app/assets/javascripts/discourse/adapters/rest.js.es6 b/app/assets/javascripts/discourse/adapters/rest.js.es6 index fb5f829f538..959bf9beee4 100644 --- a/app/assets/javascripts/discourse/adapters/rest.js.es6 +++ b/app/assets/javascripts/discourse/adapters/rest.js.es6 @@ -1,35 +1,8 @@ const ADMIN_MODELS = ['plugin']; -const _identityMap = {}; - -const RestModel = Ember.Object.extend({ - update(attrs) { - const self = this, - type = this.get('__type'); - return this.store.update(type, this.get('id'), attrs).then(function(result) { - if (result && result[type]) { - Object.keys(result).forEach(function(k) { - attrs[k] = result[k]; - }); - } - self.setProperties(attrs); - return result; - }); - }, - - destroyRecord() { - const type = this.get('__type'); - return this.store.destroyRecord(type, this.get('id')); - } -}); - export default Ember.Object.extend({ - serverName(type) { - return Ember.String.underscore(type + 's'); - }, - pathFor(type, id) { - let path = "/" + this.serverName(type); + let path = "/" + Ember.String.underscore(type + 's'); if (ADMIN_MODELS.indexOf(type) !== -1) { path = "/admin/" + path; } if (id) { path += "/" + id; } @@ -37,66 +10,22 @@ export default Ember.Object.extend({ return path; }, - findAll(type) { - var self = this; - return Discourse.ajax(this.pathFor(type)).then(function(result) { - return result[self.serverName(type)].map(obj => self._hydrate(type, obj)); - }); + findAll(store, type) { + return Discourse.ajax(this.pathFor(type)); }, - find(type, id) { - var self = this; - return Discourse.ajax(this.pathFor(type, id)).then(function(result) { - return self._hydrate(type, result[Ember.String.underscore(type)]); - }); + find(store, type, id) { + return Discourse.ajax(this.pathFor(type, id)); }, - update(type, id, attrs) { + update(store, type, id, attrs) { const data = {}; data[Ember.String.underscore(type)] = attrs; - - return Discourse.ajax(this.pathFor(type, id), { method: 'PUT', data }).then(function (result) { - if (result && result[type] && result[type].id) { - const oldRecord = _identityMap[type][id]; - delete _identityMap[type][id]; - _identityMap[type][result[type].id] = oldRecord; - } - return result; - }); + return Discourse.ajax(this.pathFor(type, id), { method: 'PUT', data }); }, - destroyRecord(type, id) { - return Discourse.ajax(this.pathFor(type, id), { method: 'DELETE' }).then(function(result) { - const forType = _identityMap[type]; - if (forType) { delete forType[id]; } - return result; - }); - }, - - createRecord(type, attrs) { - return this._hydrate(type, attrs); - }, - - _hydrate(type, obj) { - if (!obj) { throw "Can't hydrate " + type + " of `null`"; } - if (!obj.id) { throw "Can't hydrate " + type + " without an `id`"; } - - _identityMap[type] = _identityMap[type] || {}; - - const existing = _identityMap[type][obj.id]; - if (existing) { - delete obj.id; - existing.setProperties(obj); - return existing; - } - - obj.store = this; - obj.__type = type; - - const klass = this.container.lookupFactory('model:' + type) || RestModel; - const model = klass.create(obj); - _identityMap[type][obj.id] = model; - return model; + destroyRecord(store, type, record) { + return Discourse.ajax(this.pathFor(type, record.get('id')), { method: 'DELETE' }); } }); diff --git a/app/assets/javascripts/discourse/models/store.js.es6 b/app/assets/javascripts/discourse/models/store.js.es6 index ef99031681a..a55d8849ab8 100644 --- a/app/assets/javascripts/discourse/models/store.js.es6 +++ b/app/assets/javascripts/discourse/models/store.js.es6 @@ -1,21 +1,87 @@ +const _identityMap = {}; + +const RestModel = Ember.Object.extend({ + update(attrs) { + const self = this, + type = this.get('__type'); + return this.store.update(type, this.get('id'), attrs).then(function(result) { + if (result && result[type]) { + Object.keys(result).forEach(function(k) { + attrs[k] = result[k]; + }); + } + self.setProperties(attrs); + return result; + }); + }, + + destroyRecord() { + const type = this.get('__type'); + return this.store.destroyRecord(type, this); + } +}); + export default Ember.Object.extend({ findAll(type) { const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest'); - return adapter.findAll(type); + const self = this; + return adapter.findAll(this, type).then(function(result) { + return result[Ember.String.underscore(type + 's')].map(obj => self._hydrate(type, obj)); + }); }, find(type, id) { const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest'); - return adapter.find(type, id); + const self = this; + return adapter.find(this, type, id).then(function(result) { + return self._hydrate(type, result[Ember.String.underscore(type)]); + }); + }, + + update(type, id, attrs) { + const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest'); + return adapter.update(this, type, id, attrs, function(result) { + if (result && result[type] && result[type].id) { + const oldRecord = _identityMap[type][id]; + delete _identityMap[type][id]; + _identityMap[type][result[type].id] = oldRecord; + } + return result; + }); }, createRecord(type, attrs) { - const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest'); - return adapter.createRecord(type, attrs); + return this._hydrate(type, attrs); }, - destroyRecord(type, id) { + destroyRecord(type, record) { const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest'); - return adapter.destroyRecord(type, id); + return adapter.destroyRecord(this, type, record).then(function(result) { + const forType = _identityMap[type]; + if (forType) { delete forType[record.get('id')]; } + return result; + }); + }, + + _hydrate(type, obj) { + if (!obj) { throw "Can't hydrate " + type + " of `null`"; } + if (!obj.id) { throw "Can't hydrate " + type + " without an `id`"; } + + _identityMap[type] = _identityMap[type] || {}; + + const existing = _identityMap[type][obj.id]; + if (existing) { + delete obj.id; + existing.setProperties(obj); + return existing; + } + + obj.store = this; + obj.__type = type; + + const klass = this.container.lookupFactory('model:' + type) || RestModel; + const model = klass.create(obj); + _identityMap[type][obj.id] = model; + return model; } }); diff --git a/test/javascripts/helpers/create-pretender.js.es6 b/test/javascripts/helpers/create-pretender.js.es6 index 5751ceaa5f5..c64d4c1b6bf 100644 --- a/test/javascripts/helpers/create-pretender.js.es6 +++ b/test/javascripts/helpers/create-pretender.js.es6 @@ -99,6 +99,12 @@ export default function() { } }); + this.put('/widgets/:widget_id', function(request) { + const w = _widgets.findBy('id', parseInt(request.params.widget_id)); + const cloned = JSON.parse(JSON.stringify(w)); + return response({ widget: cloned }); + }); + this.get('/widgets', function() { return response({ widgets: _widgets }); }); diff --git a/test/javascripts/models/rest-model-test.js.es6 b/test/javascripts/models/rest-model-test.js.es6 new file mode 100644 index 00000000000..0f0ea282961 --- /dev/null +++ b/test/javascripts/models/rest-model-test.js.es6 @@ -0,0 +1,24 @@ +module('rest-model'); + +import createStore from 'helpers/create-store'; + +test('update', function() { + const store = createStore(); + + store.find('widget', 123).then(function(widget) { + equal(widget.get('name'), 'Trout Lure'); + widget.update({ name: 'new name' }).then(function() { + equal(widget.get('name'), 'new name'); + }); + }); +}); + +test('destroyRecord', function() { + const store = createStore(); + store.find('widget', 123).then(function(widget) { + widget.destroyRecord().then(function(result) { + ok(result); + }); + }); +}); + diff --git a/test/javascripts/models/store-test.js.es6 b/test/javascripts/models/store-test.js.es6 index f460b4ba0eb..20f5cce30df 100644 --- a/test/javascripts/models/store-test.js.es6 +++ b/test/javascripts/models/store-test.js.es6 @@ -23,6 +23,13 @@ test('find', function() { }); }); +test('update', function() { + const store = createStore(); + store.update('widget', 123, {name: 'hello'}).then(function(result) { + ok(result); + }); +}); + test('findAll', function() { const store = createStore(); store.findAll('widget').then(function(result) { @@ -34,7 +41,9 @@ test('findAll', function() { test('destroyRecord', function() { const store = createStore(); - store.destroyRecord('widget', 124).then(function(result) { - ok(result); + store.find('widget', 123).then(function(w) { + store.destroyRecord('widget', w).then(function(result) { + ok(result); + }); }); });