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:
Defining the resource
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 es back
decoder : 'jsend',
contentType: 'application/json' // what goes there
};
amplify.request.define(resource, "ajax", definition);
});
Employing the resource
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.
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:
Defining the resource
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 es back
decoder : 'jsend',
contentType: 'application/json' // what goes there
};
amplify.request.define(resource, "ajax", definition);
});
Employing the resource
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.
Share Improve this question edited May 30, 2012 at 2:54 Charles 51.4k13 gold badges106 silver badges144 bronze badges asked May 29, 2012 at 23:55 Brian M. HuntBrian M. Hunt 83.8k76 gold badges234 silver badges349 bronze badges2 Answers
Reset to default 9You 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!