Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Amplify.js - CRUD-like urls

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 comes 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.

like image 274
Brian M. Hunt Avatar asked May 29 '12 23:05

Brian M. Hunt


2 Answers

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;
like image 145
Doug Neiner Avatar answered Sep 22 '22 05:09

Doug Neiner


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!

like image 32
Germán Avatar answered Sep 20 '22 05:09

Germán