chore: add support for scope_id in URL prefixes and method in URL suffixes

This commit is contained in:
Randall Morey committed 2020-07-15 16:23:38 -04:00
1 parent 89b736744f
commit 9f48f8c85e
3 files changed
+195 -31

No files matched your search

+35 -1
View File
@@ -1,7 +1,7 @@
import RESTAdapter from '@ember-data/adapter/rest';
import AdapterBuildURLMixin from '../mixins/adapter-build-url';
import config from 'ember-get-config';
import { get } from '@ember/object';
import { get, getWithDefault } from '@ember/object';
import { InvalidError } from '@ember-data/adapter/error';
import { dasherize } from '@ember/string';
import { pluralize } from 'ember-inflector';
@@ -58,6 +58,40 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
// =methods
/**
* Prepends a scope to the URL prefix, if a scope is passed via the
* snapshot's `adapterOptions.scope_id` field.
* @override
* @param {string} path
* @param {string} parentURL
* @param {string} modelName
* @param {string} id
* @param {object} snapshot
* @return {string}
*/
urlPrefix(path, parentURL, modelName, id, snapshot={}) {
const prefix = super.urlPrefix(...arguments);
let scopePath = getWithDefault(snapshot, 'adapterOptions.scope_id', '');
// Ensure a slash is added between prefix + scope path if needed.
if (scopePath && prefix.charAt(prefix.length - 1) !== '/') {
scopePath = `/${scopePath}`;
}
return `${prefix}${scopePath}`;
}
/**
* Appends a custom method after a colon, if a method is passed via the
* snapshot's `adapterOptions.method` field.
* @param {string} modelName
* @param {string} id
* @param {object} snapshot
* @return {string}
*/
urlSuffix(modelName, id, snapshot={}) {
const method = getWithDefault(snapshot, 'adapterOptions.method', '');
return method ? `:${method}` : '';
}
/**
* Transforms the type to a dasherized string used in our API paths.
*
+104 -29
View File
@@ -16,36 +16,35 @@ export default Mixin.create({
// =methods
/**
* This override behaves identically to the default method by default.
* It exists only to document the additional paramters to the method.
* @override
* @param {string} path
* @param {string} parentURL
* @param {string} modelName
* @param {string} id
* @param {object} snapshot
* @return {string} urlPrefix
*/
urlPrefix(/* path, parentURL, modelName, id, snapshot */) {
// What's this super syntax?
// Ember mixins are still based on the older Ember Object, rather than
// native ES classes. Thus we have to call super in this strange way.
// https://blog.emberjs.com/2019/01/26/emberjs-native-class-update-2019-edition.html
return this._super(...arguments);
},
/**
* This override behaves identically to the default method by default.
* It exists only to document the additional paramters to the method.
* @override
* @param {string} path
* @param {string} parentURL
* @param {string} modelName
* @param {string} id
* @param {object} snapshot
* @return {string} urlPrefix
*/
urlPrefix(/* path, parentURL, modelName, id, snapshot */) {
// What's this super syntax?
// Ember mixins are still based on the older Ember Object, rather than
// native ES classes. Thus we have to call super in this strange way.
// https://blog.emberjs.com/2019/01/26/emberjs-native-class-update-2019-edition.html
return this._super(...arguments);
},
/**
* Generates a string to be appended to a URL. Empty string by default.
* @param {string} modelName
* @param {string} id
* @param {?object} snapshot
* @return {string}
*/
urlSuffix(/* modelName, id, snapshot */) {
return '';
},
/**
* Generates a string to be appended to a URL. Empty string by default.
* @param {string} modelName
* @param {string} id
* @param {?object} snapshot
* @return {string}
*/
urlSuffix(/* modelName, id, snapshot */) {
return '';
},
/**
* Overrides the default `_buildURL` with a nearly identical version.
@@ -73,6 +72,82 @@ export default Mixin.create({
url = url.join('/');
if (!host && url && url.charAt(0) !== '/') url = '/' + url;
return `${url}${suffix}`;
},
/**
* Overrides the default method simply to pass an additional argument
* `snapshot` to the `_buildURL` method.
* @override
* @param {string} id
* @param {string} modelName
* @param {object} snapshot
* @return {string}
*/
urlForFindRecord(id, modelName, snapshot) {
return this._buildURL(modelName, id, snapshot);
},
/**
* Overrides the default method simply to pass an additional argument
* `snapshot` to the `_buildURL` method.
* @override
* @param {string} modelName
* @param {object} snapshot
* @return {string}
*/
urlForFindAll(modelName, snapshot) {
return this._buildURL(modelName, null, snapshot);
},
/**
* Overrides the default method simply to pass an additional argument
* `snapshot` to the `_buildURL` method.
* @override
* @param {string} id
* @param {string} modelName
* @param {object} snapshot
* @return {string}
*/
urlForFindBelongsTo(id, modelName, snapshot) {
return this._buildURL(modelName, id, snapshot);
},
/**
* Overrides the default method simply to pass an additional argument
* `snapshot` to the `_buildURL` method.
* @override
* @param {string} modelName
* @param {object} snapshot
* @return {string}
*/
urlForCreateRecord(modelName, snapshot) {
return this._buildURL(modelName, null, snapshot);
},
/**
* Overrides the default method simply to pass an additional argument
* `snapshot` to the `_buildURL` method.
* @override
* @param {string} id
* @param {string} modelName
* @param {object} snapshot
* @return {string}
*/
urlForUpdateRecord(id, modelName, snapshot) {
return this._buildURL(modelName, id, snapshot);
},
/**
* Overrides the default method simply to pass an additional argument
* `snapshot` to the `_buildURL` method.
* @override
* @param {string} id
* @param {string} modelName
* @param {object} snapshot
* @return {string}
*/
urlForDeleteRecord(id, modelName, snapshot) {
return this._buildURL(modelName, id, snapshot);
}
});
@@ -18,9 +18,64 @@ module('Unit | Adapter | application', function (hooks) {
});
test('it generates correct URL prefixes', function (assert) {
assert.expect(2);
const adapter = this.owner.lookup('adapter:application');
assert.ok(config.api.namespace);
assert.equal(adapter.urlPrefix(), config.api.namespace);
});
test('it generates URL prefixes with optional `scope_id` from adapterOptions', function (assert) {
assert.expect(2);
const scope_id = 'global';
const adapter = this.owner.lookup('adapter:application');
const prefix = adapter.urlPrefix(null, null, null, null, {
adapterOptions: {scope_id}
});
assert.ok(config.api.namespace);
assert.equal(prefix, `v1/${scope_id}`);
});
test('it generates correct default URL suffixes', function (assert) {
assert.expect(1);
const adapter = this.owner.lookup('adapter:application');
assert.equal(adapter.urlPrefix(), config.api.namespace);
assert.equal(adapter.urlSuffix(), '');
});
test('it generates URL suffixes with optional `method` from adapterOptions', function (assert) {
assert.expect(2);
const method = 'set-something';
const adapter = this.owner.lookup('adapter:application');
const suffix = adapter.urlSuffix(null, null, {
adapterOptions: {method}
});
assert.ok(config.api.namespace);
assert.equal(suffix, ':set-something');
});
test('it generates correct complete URLs', function (assert) {
assert.expect(6);
const scope_id = 'o_1';
const method = 'my-custom-method';
const mockSnapshot = {
adapterOptions: {
scope_id,
method
}
};
const adapter = this.owner.lookup('adapter:application');
// test URL generation for each request type...
const findRecordURL = adapter.buildURL('project', '1', mockSnapshot, 'findRecord');
assert.equal(findRecordURL, '/v1/o_1/projects/1:my-custom-method');
const findAllURL = adapter.buildURL('project', null, mockSnapshot, 'findAll');
assert.equal(findAllURL, '/v1/o_1/projects:my-custom-method');
const findBelongsToURL = adapter.buildURL('project', '2', mockSnapshot, 'findBelongsTo');
assert.equal(findBelongsToURL, '/v1/o_1/projects/2:my-custom-method');
const createRecordURL = adapter.buildURL('project', null, mockSnapshot, 'createRecord');
assert.equal(createRecordURL, '/v1/o_1/projects:my-custom-method');
const updateRecordURL = adapter.buildURL('project', '3', mockSnapshot, 'updateRecord');
assert.equal(updateRecordURL, '/v1/o_1/projects/3:my-custom-method');
const deleteRecordURL = adapter.buildURL('project', '4', mockSnapshot, 'deleteRecord');
assert.equal(deleteRecordURL, '/v1/o_1/projects/4:my-custom-method');
});
test('it rewrites PUT to PATCH, but leaves others unchanged', function (assert) {