Reputation: 605
TL; DR: Where and how do you call the normalize method, to format the servers response into what the store is expecting?
I am overriding the Adapter to create a JSON RPC adapter, and having some trouble with normalizing the server's response - problem is I don't know where to call Normalize, ie:
createRecord: function(store, type, record){
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record, { includeId: true });
var params = data[type.typeKey];
return this.send('create', [params], null, type.typeKey, null, null, null);
}
What Send does is creates an ajax request:
send: function(method, args, kwargs, model, url, success, error){
var data = JSON.stringify(this.getData(model, method, args, kwargs, success, error));
var settings = this.getSettings(data, success, error);
return $.ajax(this.get('host')+'/'+this.get('namespace'), settings);
}
GetData formats the JSON to be sent to the server into something like
{"id":1,"method":"call","jsonrpc":"2.0","params":{"model":"user","method":"create","args":[{"username":"dsadfdasf"}],"kwargs":{"context":"elink"}}}
and finally getSettings:
getSettings: function(data, success, error){
var settings = {};
settings.type = 'POST';
settings.data = data;
settings.success = success || function(data){
data[JSON.parse(settings.data).params.model] = data.result[0];
delete data.result;
delete data.jsonrpc;
delete data.id;
};
settings.error = error || function(xhr){
cconsole.log('ERROR:' + xhr);
};
return settings;
}
Here, getSettings.success does its own normalization, since the returned object is always in this format: {"result":[{"username":"billyJoe","id":11}],"jsonrpc":"2.0","id":15223}
What it does is removes the jsonrpc and id attributes, 'renames' the result into the requested model name (into user), turns it into an object instead of a list, and in the end you get: {"user":{"username":"billyJoe","id":11}}
which is what the store would expect for createRecord, or find(model, id). However, if querying for records where the controller expects multiple users inside a list:
{"users":[{"username":"billyJoe","id":11}]}
(notice 'userS' and the [] ).
so I need a normalizer to format the data based on which function is making the call.
Finally the question: where exactly do I call Normalize? I cant call it in getSettings because it doesn't have a reference to the store (should I be passing a reference to the store deeper through calls?)
I would call it in createRecord but it returns a promise, not the actual response I am looking for (do I somehow use then to wait for the data?)
Do I take it further and override model.save() and store.find() to normalize?
I know the questions seem silly, and all of these are possibilities, but I am looking for the most proper way.
Upvotes: 0
Views: 441
Reputation: 483
The normalization would occur in your handling of the response in your send
method. Here is how it is done in the DS.RestAdapter (Source):
ajax: function(url, type, options) {
var adapter = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
var hash = adapter.ajaxOptions(url, type, options);
hash.success = function(json, textStatus, jqXHR) {
json = adapter.ajaxSuccess(jqXHR, json);
if (json instanceof InvalidError) {
Ember.run(null, reject, json);
} else {
Ember.run(null, resolve, json);
}
};
hash.error = function(jqXHR, textStatus, errorThrown) {
Ember.run(null, reject, adapter.ajaxError(jqXHR, jqXHR.responseText));
};
Ember.$.ajax(hash);
}, "DS: RESTAdapter#ajax " + type + " to " + url);
}
This ajax
function would be what you're trying to do in your send
method.
This function built the request (the hash
object) and then sent it via ajax.
Your normalize function would be called when the request is successful and would be passed the response data (in the DS example above, this happens with the json = adapter.ajaxSuccess(jqXHR, json);
call. After normalization, you resolve the promise with the normalized data which was done with the Ember.run(null, resolve, json);
call.
Upvotes: 1