refactor: 💡 model grants as a fragment-array for statefulness

This commit is contained in:
Randall Morey committed 2020-08-07 18:19:58 -04:00
1 parent 3b09ec80cd
commit e142e99fdb
8 files changed
+98 -10

No files matched your search

@@ -33,4 +33,10 @@ export default class GeneratedRoleModel extends BaseModel {
description: 'Whether the resource is disabled',
})
disabled;
@attr('number', {
description: 'Current version number of this resource.',
})
version;
}
@@ -0,0 +1,16 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
/**
* Represents an item in an array of strings.
*/
export default class FragmentStringModel extends Fragment {
// =attributes
@attr('string', {
description: 'The value of the string.'
})
value;
}
+2 -2
View File
@@ -1,5 +1,5 @@
import GeneratedRoleModel from '../generated/models/role';
import { array } from 'ember-data-model-fragments/attributes';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
export default class RoleModel extends GeneratedRoleModel {
@@ -9,7 +9,7 @@ export default class RoleModel extends GeneratedRoleModel {
* Grants is read-only _most_ under normal circumstances. But grants can
* be persisted via a dedicated call to `saveGrants()`.
*/
@array({readOnly: true}) grants;
@fragmentArray('fragment-string', {readOnly: true}) grants;
// =methods
+19 -2
View File
@@ -7,7 +7,7 @@ export default class RoleSerializer extends ApplicationSerializer {
/**
* If `adapterOptions.serializeGrants` is true, the serialization should
* include **only grants** and nothing else. Normally, grants are not
* include **only grants** and the version. Normally, grants are not
* serialized.
* @override
* @param {Snapshot} snapshot
@@ -27,8 +27,25 @@ export default class RoleSerializer extends ApplicationSerializer {
*/
serializeWithGrants(snapshot) {
return {
grants: snapshot.attr('grants')
version: snapshot.attr('version'),
grants: snapshot.attr('grants').map(grant => grant.attr('value'))
};
}
/**
* Converts string arrays to object arrays for use with `fragment-string`.
* E.g. `"foo"` -> `{value: "foo"}`
* @override
* @param {Model} typeClass
* @param {Object} hash
* @return {Object}
*/
normalize(modelClass, resourceHash) {
// TODO: can fragment string normalization be handled generically?
if (resourceHash.grants) {
resourceHash.grants = resourceHash.grants.map(value => ({ value }));
}
return super.normalize(modelClass, resourceHash);
}
}
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/models/fragment-string';
@@ -0,0 +1,13 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Model | fragment string', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let store = this.owner.lookup('service:store');
let model = store.createRecord('fragment-string', {});
assert.ok(model);
});
});
+4 -2
View File
@@ -17,7 +17,8 @@ module('Unit | Model | role', function (hooks) {
this.server.post('/v1/scopes/o_1/roles/123abc:set-grants', (schema, request) => {
const body = JSON.parse(request.requestBody);
assert.deepEqual(body, {
grants: ['grant1', 'grant2']
grants: ['grant1', 'grant2'],
version: 1
});
});
const store = this.owner.lookup('service:store');
@@ -28,7 +29,8 @@ module('Unit | Model | role', function (hooks) {
attributes: {
name: 'Role',
description: 'Description',
grants: ['grant1', 'grant2'],
grants: [{value: 'grant1'}, {value: 'grant2'}],
version: 1,
scope: {
scope_id: 'o_1',
type: 'scope'
+37 -4
View File
@@ -11,14 +11,16 @@ module('Unit | Serializer | role', function(hooks) {
const record = store.createRecord('role', {
name: 'User',
description: 'Description',
grants: ['foo', 'bar']
grants: [{value: 'foo'}, {value: 'bar'}],
version: 1
});
const snapshot = record._createSnapshot();
snapshot.adapterOptions = {};
const serializedRecord = serializer.serialize(snapshot);
assert.deepEqual(serializedRecord, {
name: 'User',
description: 'Description'
description: 'Description',
version: 1
});
});
@@ -29,7 +31,8 @@ module('Unit | Serializer | role', function(hooks) {
const record = store.createRecord('role', {
name: 'User',
description: 'Description',
grants: ['foo', 'bar']
grants: [{value: 'foo'}, {value: 'bar'}],
version: 1
});
const snapshot = record._createSnapshot();
snapshot.adapterOptions = {
@@ -37,7 +40,37 @@ module('Unit | Serializer | role', function(hooks) {
};
const serializedRecord = serializer.serialize(snapshot);
assert.deepEqual(serializedRecord, {
grants: ['foo', 'bar']
grants: ['foo', 'bar'],
version: 1
});
});
test('it normalizes records with array fields', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const serializer = store.serializerFor('role');
const roleModelClass = store.createRecord('role').constructor;
const payload = {
id: '1',
name: 'Role 1',
grants: ['*', '*']
};
const normalized = serializer.normalizeSingleResponse(
store,
roleModelClass,
payload
);
assert.deepEqual(normalized, {
included: [],
data: {
id: '1',
type: 'role',
attributes: {
name: 'Role 1',
grants: [{value: '*'}, {value: '*'}],
},
relationships: {},
},
});
});