chore: 🤖 improve adapters and serializers to match API
This commit is contained in:
6 files changed
+97
-3
No files matched your search
@@ -18,4 +18,23 @@ export default class ApplicationAdapter extends RESTAdapter {
|
||||
* @type {string}
|
||||
*/
|
||||
namespace = get(config, 'api.namespace');
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Overrides default ajax method by rewritting PUT requests as PATCH.
|
||||
* PATCH is the request method used by our API for updates.
|
||||
*
|
||||
* @override
|
||||
* @method ajax
|
||||
* @private
|
||||
* @param {String} url
|
||||
* @param {String} type The request type GET, POST, PUT, DELETE etc.
|
||||
* @param {Object} options
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
ajax(url, type, options) {
|
||||
const method = type === 'PUT' ? 'PATCH' : type;
|
||||
return super.ajax(url, method, options);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,22 @@
|
||||
import Model from '@ember-data/model';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
export default class BaseModel extends Model {}
|
||||
export default class BaseModel extends Model {
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('hasDirtyAttributes', 'isSaving')
|
||||
get canSave() {
|
||||
return this.hasDirtyAttributes && !this.isSaving;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('canSave')
|
||||
get cannotSave() {
|
||||
return !this.canSave;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
/**
|
||||
* If an attribute is annotated as readOnly in the model, don't serialize it.
|
||||
* Otherwise delegate to default attribute serializer.
|
||||
*
|
||||
* @override
|
||||
* @method serializeAttribute
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {Object} json
|
||||
@@ -30,6 +32,23 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
return options.readOnly ? null : super.serializeAttribute(...arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* In our API, request payloads are unrooted. But Ember Data roots request
|
||||
* payloads for this adapter by default. Instead of assigned a root key
|
||||
* on the outgoing hash, we copy the serialized attributes into it.
|
||||
*
|
||||
* @override
|
||||
* @method serializeIntoHash
|
||||
* @param {Object} hash
|
||||
* @param {Model} typeClass
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {Object} options
|
||||
*/
|
||||
serializeIntoHash(hash, typeClass, snapshot, options) {
|
||||
const serialized = this.serialize(snapshot, options);
|
||||
Object.assign(hash, serialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* In our API, array payloads are always rooted under the same key `items`.
|
||||
* Ember Data normally expects them to be rooted under their model name,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import config from 'ember-get-config';
|
||||
import RESTAdapter from '@ember-data/adapter/rest';
|
||||
|
||||
module('Unit | Adapter | application', function (hooks) {
|
||||
setupTest(hooks);
|
||||
@@ -17,4 +18,14 @@ module('Unit | Adapter | application', function (hooks) {
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
assert.equal(adapter.urlPrefix(), config.api.namespace);
|
||||
});
|
||||
|
||||
test('it rewrites PUT to PATCH, but leaves others unchanged', function (assert) {
|
||||
assert.expect(1);
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
// TODO this is icky, should be changed to a spy or stub
|
||||
RESTAdapter.prototype.ajax = (url, type) => {
|
||||
assert.equal(type, 'PATCH');
|
||||
};
|
||||
adapter.ajax('/', 'PUT');
|
||||
});
|
||||
});
|
||||
@@ -10,4 +10,30 @@ module('Unit | Model | base', function (hooks) {
|
||||
let model = store.createRecord('base', {});
|
||||
assert.ok(model);
|
||||
});
|
||||
|
||||
test('it has canSave and cannotSave attributes', function (assert) {
|
||||
assert.expect(8);
|
||||
const store = this.owner.lookup('service:store');
|
||||
store.push({
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'project',
|
||||
attributes: {},
|
||||
},
|
||||
});
|
||||
const model = store.peekRecord('project', '1');
|
||||
assert.equal(model.canSave, false);
|
||||
assert.equal(model.cannotSave, true);
|
||||
// Should be able to save if dirty
|
||||
model.name = 'Project';
|
||||
assert.equal(model.hasDirtyAttributes, true);
|
||||
assert.equal(model.canSave, true);
|
||||
assert.equal(model.cannotSave, false);
|
||||
// Should not be able to save while currently saving
|
||||
model.transitionTo('updated.inFlight');
|
||||
assert.equal(model.isSaving, true);
|
||||
assert.equal(model.canSave, false);
|
||||
assert.equal(model.cannotSave, true);
|
||||
model.transitionTo('loaded');
|
||||
});
|
||||
});
|
||||
@@ -75,7 +75,7 @@ module('Unit | Serializer | application', function (hooks) {
|
||||
const projectModelClass = store.createRecord('project').constructor;
|
||||
const payload = {
|
||||
id: '1',
|
||||
name: 'Project 1'
|
||||
name: 'Project 1',
|
||||
};
|
||||
const normalized = serializer.normalizeSingleResponse(
|
||||
store,
|
||||
@@ -89,7 +89,7 @@ module('Unit | Serializer | application', function (hooks) {
|
||||
type: 'project',
|
||||
attributes: { name: 'Project 1' },
|
||||
relationships: {},
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user