diff --git a/app/assets/javascripts/discourse/adapters/rest.js.es6 b/app/assets/javascripts/discourse/adapters/rest.js.es6 index 3d86fe934c7..5ace5dc40be 100644 --- a/app/assets/javascripts/discourse/adapters/rest.js.es6 +++ b/app/assets/javascripts/discourse/adapters/rest.js.es6 @@ -66,10 +66,14 @@ export default EmberObject.extend({ pathFor(store, type, findArgs) { let path = this.basePath(store, type, findArgs) + - Ember.String.underscore(store.pluralize(type)); + Ember.String.underscore(store.pluralize(this.apiNameFor(type))); return this.appendQueryParams(path, findArgs); }, + apiNameFor(type) { + return type; + }, + findAll(store, type, findArgs) { return ajax(this.pathFor(store, type, findArgs)).catch(rethrow); }, @@ -104,7 +108,7 @@ export default EmberObject.extend({ update(store, type, id, attrs) { const data = {}; - const typeField = Ember.String.underscore(type); + const typeField = Ember.String.underscore(this.apiNameFor(type)); data[typeField] = attrs; return ajax( @@ -117,7 +121,7 @@ export default EmberObject.extend({ createRecord(store, type, attrs) { const data = {}; - const typeField = Ember.String.underscore(type); + const typeField = Ember.String.underscore(this.apiNameFor(type)); data[typeField] = attrs; return ajax(this.pathFor(store, type), this.getPayload("POST", data)).then( function(json) { diff --git a/app/assets/javascripts/discourse/models/store.js.es6 b/app/assets/javascripts/discourse/models/store.js.es6 index a5caad53a14..841def676ff 100644 --- a/app/assets/javascripts/discourse/models/store.js.es6 +++ b/app/assets/javascripts/discourse/models/store.js.es6 @@ -93,7 +93,12 @@ export default EmberObject.extend({ if (typeof findArgs === "object") { return this._resultSet(type, result, findArgs); } else { - return this._hydrate(type, result[Ember.String.underscore(type)], result); + const apiName = this.adapterFor(type).apiNameFor(type); + return this._hydrate( + type, + result[Ember.String.underscore(apiName)], + result + ); } }, @@ -147,8 +152,11 @@ export default EmberObject.extend({ }, refreshResults(resultSet, type, url) { + const adapter = this.adapterFor(type); return ajax(url).then(result => { - const typeName = Ember.String.underscore(this.pluralize(type)); + const typeName = Ember.String.underscore( + this.pluralize(adapter.apiNameFor(type)) + ); const content = result[typeName].map(obj => this._hydrate(type, obj, result) ); @@ -157,8 +165,11 @@ export default EmberObject.extend({ }, appendResults(resultSet, type, url) { + const adapter = this.adapterFor(type); return ajax(url).then(result => { - let typeName = Ember.String.underscore(this.pluralize(type)); + const typeName = Ember.String.underscore( + this.pluralize(adapter.apiNameFor(type)) + ); let pageTarget = result.meta || result; let totalRows = @@ -211,7 +222,10 @@ export default EmberObject.extend({ }, _resultSet(type, result, findArgs) { - const typeName = Ember.String.underscore(this.pluralize(type)); + const adapter = this.adapterFor(type); + const typeName = Ember.String.underscore( + this.pluralize(adapter.apiNameFor(type)) + ); const content = result[typeName].map(obj => this._hydrate(type, obj, result) ); diff --git a/test/javascripts/helpers/create-store.js.es6 b/test/javascripts/helpers/create-store.js.es6 index f0c55cd3860..8eccc0d6eaf 100644 --- a/test/javascripts/helpers/create-store.js.es6 +++ b/test/javascripts/helpers/create-store.js.es6 @@ -5,7 +5,7 @@ import TopicListAdapter from "discourse/adapters/topic-list"; import TopicTrackingState from "discourse/models/topic-tracking-state"; import { buildResolver } from "discourse-common/resolver"; -export default function() { +export default function(customLookup = () => {}) { const resolver = buildResolver("discourse").create(); return Store.create({ @@ -34,6 +34,7 @@ export default function() { this._settings = this._settings || Discourse.SiteSettings; return this._settings; } + return customLookup(type); }, lookupFactory(type) { diff --git a/test/javascripts/models/rest-model-test.js.es6 b/test/javascripts/models/rest-model-test.js.es6 index c737eb965ae..c5e66c4867f 100644 --- a/test/javascripts/models/rest-model-test.js.es6 +++ b/test/javascripts/models/rest-model-test.js.es6 @@ -2,6 +2,7 @@ QUnit.module("rest-model"); import createStore from "helpers/create-store"; import RestModel from "discourse/models/rest"; +import RestAdapter from "discourse/adapters/rest"; QUnit.test("munging", assert => { const store = createStore(); @@ -101,3 +102,37 @@ QUnit.test("destroyRecord", assert => { }); }); }); + +QUnit.test("custom api name", async assert => { + const store = createStore(type => { + if (type === "adapter:my-widget") { + return RestAdapter.extend({ + // An adapter like this is used when the server-side key/url + // do not match the name of the es6 class + apiNameFor() { + return "widget"; + } + }).create(); + } + }); + + // The pretenders only respond to requests for `widget` + // If these basic tests pass, the name override worked correctly + + //Create + const widget = store.createRecord("my-widget"); + await widget.save({ name: "Evil Widget" }); + assert.equal(widget.id, 100, "it saved a new record successully"); + assert.equal(widget.get("name"), "Evil Widget"); + + // Update + await widget.update({ name: "new name" }); + assert.equal(widget.get("name"), "new name"); + + // Destroy + await widget.destroyRecord(); + + // Lookup + const foundWidget = await store.find("my-widget", 123); + assert.equal(foundWidget.name, "Trout Lure"); +});