I am using amplify.request, and I would like to have CRUD-like URLs when sending data to and from the server. Here is an example:
resources = {
"document_create" : ['/d/crud/', "POST"],
"document_read" : ['/d/crud/{id}', "GET"],
"document_update" : ['/d/crud/{id}', "PUT"],
"document_delete" : ['/d/crud/{id}', "DELETE"]
};
$.each(resources, function (resource, settings) {
definition = {
url : settings[0],
type : settings[1],
dataType: "json", // what comes back
decoder : 'jsend',
contentType: 'application/json' // what goes there
};
amplify.request.define(resource, "ajax", definition);
});
function make_request(resource, params, success_cb, error_cb) {
if (this.is_post(resource)) {
// this.is_post is a test, defined elsewhere, to see if this is a POST request
params = JSON.stringify(params);
}
amplify.request(
resourceId: resource
data: params
success: success_cb
error: error_cb
);
}
This works fine for create
and read
and `delete, like-so:
make_request('document_delete', {id: 1}, cb)
However, for update
, since the content is being passed as JSON, the URL substitution does not occur as intended.
Is there a way to take advantage of the URL substitution for {id}
in the above scheme?
The only alternative I can think of is to pass the data to the server URL-encoded. Unfortunately this is somewhat problematic, and I would prefer to be able to retain the use of CRUD-like URLs and saving with JSON formatted data, if that is possible.
Thoughts would be appreciated.
You could define your own request type, or you could just listen for request.ajax.preprocess
and do your JSON.stringify
there – which is after the URL substitution has occurred.
The is_post
is presumably the same code you have now, just put in a different place. It's not a magic function :)
amplify.subscribe( "request.ajax.preprocess", function( defnSettings, settings, ajaxSettings ) {
if ( is_post( defnSettings.resourceId ) ) {
// This will still include the variable that matches the URL substitution:
var _settings = $.extend( true, {}, defnSettings.data, settings.data, ajaxSettings.data );
ajaxSettings.data = JSON.stringify( _settings );
}
});
Your make_request
would no longer stringify
:
function make_request(resource, params, success_cb, error_cb) {
amplify.request(
resourceId: resource
data: params
success: success_cb
error: error_cb
);
}
Then your request can be run as normal:
make_request('document_update', {id: 1, title: "New Title" }, cb)
Important: the way I wrote the preprocess call, it will not remove the id
even though it matched the URL (Amplify would normally delete the matched key). If you want it to remove the id
from the stringified JSON, replace the _settings
assignment with this:
_settings = ajaxSettings.data;
As of Amplify 1.1.0 there is a dataMap option when defining resources. If you pass a function instead of hash object, amplify will call this function with the raw data passed to the request.
In this example I pass JSON.stringify to the dataMap option.
amplify.request.define("paqueteput", "ajax", {
url: "/api/paquetes/{id}",
dataType: "json",
type: "PUT",
contentType: "application/json; charset=utf-8",
dataMap: JSON.stringify
});
// later we pass a raw object that gets stringified to JSON
var savePaquete = function(paquete, cb) {
amplify.request({
resourceId: "paqueteput",
data: paquete,
success: cb.sucess,
error: cb.error
});
};
The only thing that I don't really like is that amplify deletes the keys mapped in the url from your data object. In this case, the id property gets deleted from the final JSON, although it is present in the url.
There should be an option in amplify to control this behavior!
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