REST (Representational State Transfer) ************************************** .. note:: This is an experimental feature. ``qx.io.rest.Resource`` allows to encapsulate the specifics of a REST interface. Rather than requesting URLs with a specific HTTP method manually, a resource representing the remote resource is instantiated and **actions** are invoked on this resource. A resource with its actions can be configured declaratively or programatically. Configuring actions =================== Given a REST-like interface with URLs that comply to the following pattern. :: GET /photo/{id} PUT /photo/{id} DELETE /photo/{id} GET /photos POST /photos Note ``{id}`` stands for a placeholder. This interface comprises of two resources: ``photo`` and ``photos``. To declare the specifics of the REST interface declaratively, pass a description to the constructor. :: // Singular resource var photo = new qx.io.rest.Resource({ // Retrieve photo get: { method: "GET", url: "/photo/{id}" }, // Update photo put: { method: "POST", url: "/photo/{id}" }, // Delete photo del: { method: "DELETE", url: "/photo/{id}" } }); // Plural resource var photos = new qx.io.rest.Resource({ // Retrieve list of photos get: { method: "GET", url: "/photos" }, // Create photo post: { method: "POST", url: "/photos" } }); Or programmatically, for each action. :: var photo = new qx.io.rest.Resource(); photo.map("get", "GET", "/photo/{id}"); Invoking actions ================ Once configured, actions can be invoked. They are invoked by calling a method that is dynamically added to the resource on configuration of the action. :: photo.get({id: 1}); // Alternatively: photo.invoke("get", {id: 1}); // --> GET /photo/1 photos.get(); // Alternatively: photos.invoke("get"); // --> GET /photos When an action is invoked, an appropriate request is configured and send automatically. Parameters ========== If the URL contains parameters, the position where the parameters should be inserted can be specified by using `URI templates `_. Parameters are optional unless a check is defined. A default value can be provided. :: var photo = new qx.io.rest.Resource(); photo.map("get", "GET", "/photo/{id}/{size=medium}", {id: qx.io.rest.Resource.REQUIRED}); photo.get({id: 1, size: "large"}); // --> GET /photo/1/large photo.get({id: 1}); // --> GET /photo/1/medium photo.get(); // --> Error: Missing parameter 'id' Events ====== Events are fired by the resource when the request was successful or any kind of error occurred. There are general resource events and action specific events. Handlers receive a ``qx.event.type.Rest`` event that, among other properties, includes the response. :: photo.get({id: 1}); photo.put({id: 1}); // "success" is fired when any request associated to resource receives a response photos.addListener("success", function(e) { e.getAction(); // --> "get" or "put" }); // "getSuccess" is fired when the request associated to the get action receives a response photos.addListener("getSuccess", function(e) { e.getAction(); // --> "get" }); If the same action should be invoked multiple times and the events fired for each request be handled differently, it is possible to remember the id of the action’s invocation. The ``Rest`` event includes this id. :: var getPhotoId = photo.get({id: 1}); var getLargePhotoId = photo.get({id: 1, size: "large"}); photo.addListener("getSuccess", function(e) { if (e.getId() === getLargePhotoId) { // Handle large photo } }); Helpers ======= Helpers make it easy to accomplish common tasks when working with requests. * **refresh(action)** Resend request associated to action. Uses parameters given before. * **poll(action, params)** Periodically invoke action. * **longPoll(action)** Use Ajax long-polling to update whenever new data is available. Data binding ============ A ``qx.data.store.Rest`` store can be attached to an action. Whenever a response is received, the model property of the store is updated with the marshaled response. :: var store = new qx.data.store.Rest(photos, "get"); var list = new qx.ui.form.List(); var controller = new qx.data.controller.List(null, list); store.bind("model", controller, "model"); photos.longPoll("get");