I'm working on an Ember app that is using Ember Data and the now default json-api adapter.
According to the json-api spec (http://jsonapi.org/format/#crud-deleting) when deleting a record your server should return a 200
response if the deletion is successful and the server responds with just a top level meta
key.
My current server does just this and I'm trying to figure out how to access the data in the top level meta object when using Ember Data's model.destroyRecord()
method.
myModel.destroyRecord().then(function(model){
// the returned value is the model. How can I get the actual metadata
// returned by the server?
});
The server response contains information about what exactly was deleted and looks like this:
{
"meta": {
num-deleted-a: 10,
num-deleted-b: 100,
num-deleted-c: 200
}
}
I'd like to get this information so I can display it to the user.
Thank you!
I am using the following versions:
Ember : 2.2.0
Ember Data : 2.3.3
jQuery : 1.11.3
A JSON object MUST be at the root of every JSON:API request and response containing data. This object defines a document’s “top level”. A document MUST contain at least one of the following top-level members: data: the document’s “primary data”.
Saving meta fields using the Pods JSON API is very simple. The first thing you need to do is create an array of data that you want to update, with the keys equal to the meta key and value equal to the meta value.
relationships: a relationships object describing relationships between the resource and other JSON:API resources. links: a links object containing links related to the resource. meta: a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.
Each request to get JSON data requires your JSON API ID to be passed as a query parameter. - One of the supplied query parameters must be "apiid=n" where n is your JSON API ID
After upgrading to Ember 2.6.1 and Ember 2.6.1 I was no longer able to access the store._metadataFor
property.
To get access to the metadata from a particular call I now override the serializer for the model and add a meta
property to the model itself that simply passes through the metadata.
As an example I have a record type called vote
which when saved returns some metadata.
For the model I do the following:
// Vote Model (/app/models/vote)
export default DS.Model.extend({
vote: DS.attr('number'),
// Since i don't provide a transform the values for meta are passed through in
// raw form
meta: DS.attr()
});
Then in the serializer for the vote model I do the following:
// Vote serializer (/app/serializers/vote)
import DS from "ember-data";
export default DS.JSONAPISerializer.extend({
normalizeSaveResponse(store, primaryModelClass, payload, id, requestType) {
// The metadata in the payload does get processed by default and will be
// placed into a top level `meta` key on the returned documentHash
let documentHash = this._super(store, primaryModelClass, payload, id, requestType);
// Make sure we always have an empty object assigned to the meta attribute
if(typeof(payload.meta) !== 'object'){
payload.meta = {};
}
// Move the metadata into the attributes hash for the model
documentHash.data.attributes.meta = payload.meta;
return documentHash;
}
});
Note that in the above example I'm only adding in metadata to the vote model when making a save call to the store. If you wanted to always add in the metadata then you would override the normalize
method instead of the normalizeSaveResponse
method.
Then you can access a meta
field in the results of your save call.
let vote = self.store.createRecord('vote', {
vote: voteValue
});
vote.save().then(function(result){
// this will now contain your metadata
console.info(result.get('meta'));
});
Ember does not support meta
for single model requests (find
,save
and destroyRecord
) at the moment!
If you want this you have to hook into ember internals.
The following code uses ember internals from ember 2.3 and may break in future versions!
There is the undocumented _metadataFor
function on the store
that gives you the last metadata for a given type. I use a custom initializer to always save it to the Model
:
import Ember from 'ember';
import DS from 'ember-data';
const {set} = Ember;
export function initialize(application) {
DS.Model.reopen({
meta: null,
didCommit() {
this._super(...arguments);
set(this, 'meta', this.store._metadataFor(this.constructor.modelName));
}
});
};
export default {
name: 'meta',
initialize: initialize
};
After this you can do model.save().then(() => console.log(model.get('meta')))
or model.destroyRecord.then(() => console.log(model.get('meta')))
.
Maybe checkout this ember-twiddle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With