Generated Model Bug (#15099)
* updates path help service to handle setting id of model * adds changelog entry * removes changelog entry
This commit is contained in:
parent
6c7dee4824
commit
6cfa604044
|
@ -13,6 +13,7 @@ import fieldToAttrs from 'vault/utils/field-to-attrs';
|
|||
import { resolve, reject } from 'rsvp';
|
||||
import { debug } from '@ember/debug';
|
||||
import { dasherize, capitalize } from '@ember/string';
|
||||
import { computed } from '@ember/object'; // eslint-disable-line
|
||||
import { singularize } from 'ember-inflector';
|
||||
import { withModelValidations } from 'vault/decorators/model-validations';
|
||||
|
||||
|
@ -270,7 +271,7 @@ export default Service.extend({
|
|||
},
|
||||
|
||||
urlForCreateRecord(modelType, snapshot) {
|
||||
const { id } = snapshot;
|
||||
const id = snapshot.record.mutableId; // computed property that returns either id or private settable _id value
|
||||
const path = createPath.path.slice(1, createPath.path.indexOf('{') - 1);
|
||||
return `${this.buildURL()}/${apiPath}${path}/${id}`;
|
||||
},
|
||||
|
@ -279,6 +280,17 @@ export default Service.extend({
|
|||
const path = deletePath.path.slice(1, deletePath.path.indexOf('{') - 1);
|
||||
return `${this.buildURL()}/${apiPath}${path}/${id}`;
|
||||
},
|
||||
|
||||
createRecord(store, type, snapshot) {
|
||||
return this._super(...arguments).then((response) => {
|
||||
// if the server does not return an id and one has not been set on the model we need to set it manually from the mutableId value
|
||||
if (!response?.id && !snapshot.record.id) {
|
||||
snapshot.record.id = snapshot.record.mutableId;
|
||||
snapshot.id = snapshot.record.id;
|
||||
}
|
||||
return response;
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -302,7 +314,8 @@ export default Service.extend({
|
|||
const validations = fieldGroups.reduce((obj, element) => {
|
||||
if (element.default) {
|
||||
element.default.forEach((v) => {
|
||||
obj[v.name] = [{ type: 'presence', message: `${v.name} can't be black` }];
|
||||
const key = v.options.fieldValue || v.name;
|
||||
obj[key] = [{ type: 'presence', message: `${v.name} can't be blank` }];
|
||||
});
|
||||
}
|
||||
return obj;
|
||||
|
@ -315,6 +328,18 @@ export default Service.extend({
|
|||
} catch (err) {
|
||||
// eat the error, fieldGroups is computed in the model definition
|
||||
}
|
||||
// attempting to set the id prop on a model will trigger an error
|
||||
// this computed will be used in place of the the id fieldValue -- see openapi-to-attrs
|
||||
newModel.reopen({
|
||||
mutableId: computed('id', '_id', {
|
||||
get() {
|
||||
return this._id || this.id;
|
||||
},
|
||||
set(key, value) {
|
||||
return (this._id = value);
|
||||
},
|
||||
}),
|
||||
});
|
||||
newModel.reopenClass({ merged: true });
|
||||
owner.unregister(modelName);
|
||||
owner.register(modelName, newModel);
|
||||
|
|
|
@ -29,7 +29,7 @@ export const expandOpenApiProps = function (props) {
|
|||
editType,
|
||||
helpText: description,
|
||||
possibleValues: prop['enum'],
|
||||
fieldValue: isId ? 'id' : null,
|
||||
fieldValue: isId ? 'mutableId' : null,
|
||||
fieldGroup: group || 'default',
|
||||
readOnly: isId,
|
||||
defaultValue: value || null,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{{#each-in fieldGroup as |group fields|}}
|
||||
{{#if (or (eq group "default") (eq group "Options"))}}
|
||||
{{#each fields as |attr|}}
|
||||
{{#if (not-eq attr.options.fieldValue "id")}}
|
||||
{{#if (not (includes attr.options.fieldValue (array "id" "mutableId")))}}
|
||||
<InfoTableRow
|
||||
@alwaysRender={{this.showAllFields}}
|
||||
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
|
||||
|
|
73
ui/tests/unit/services/path-helper-test.js
Normal file
73
ui/tests/unit/services/path-helper-test.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||
|
||||
const openapiStub = {
|
||||
openapi: {
|
||||
components: {
|
||||
schemas: {
|
||||
UsersRequest: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
password: {
|
||||
description: 'Password for the user',
|
||||
type: 'string',
|
||||
'x-vault-displayAttrs': { sensitive: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
paths: {
|
||||
'/users/{username}': {
|
||||
post: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: { $ref: '#/components/schemas/UsersRequest' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
parameters: [
|
||||
{
|
||||
description: 'Username for this user.',
|
||||
in: 'path',
|
||||
name: 'username',
|
||||
required: true,
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
],
|
||||
'x-vault-displayAttrs': { itemType: 'User', action: 'Create' },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
module('Unit | Service | path-help', function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.pathHelp = this.owner.lookup('service:path-help');
|
||||
this.store = this.owner.lookup('service:store');
|
||||
});
|
||||
|
||||
test('it should generate model with mutableId', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
this.server.get('/auth/userpass/', () => openapiStub);
|
||||
this.server.get('/auth/userpass/users/example', () => openapiStub);
|
||||
this.server.post('/auth/userpass/users/test', () => {
|
||||
assert.ok(true, 'POST request made to correct endpoint');
|
||||
return;
|
||||
});
|
||||
|
||||
const modelType = 'generated-user-userpass';
|
||||
await this.pathHelp.getNewModel(modelType, 'userpass', 'auth/userpass/', 'user');
|
||||
const model = this.store.createRecord(modelType);
|
||||
model.set('mutableId', 'test');
|
||||
await model.save();
|
||||
assert.equal(model.get('id'), 'test', 'model id is set to mutableId value on save success');
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue