Services are just regular controllers with a special method signature for handling http request and response events! The only difference is that jquery-claypool decorates the response object with some handy, dandy, mvc to help you cleanly separate your event handling from your presentation and data access functions. if you haven't been over the model, view, controller documentation you should probably read those first becuase we are going to dive right into a real service example.
because the server framework is built very gently on top of the general client framework, writting serverside services is the only place that jquery-claypool requires that you 'extend' an interface (using jQuery.extend). this simply provides a very light transformation of the event object into the request/response objects.
Let's start by creating a simple closure that will define our service.
/*
* @file app/services/hello.js
* @description You can feel free to use your
* own writing style, we are providing an
* example not a rigid requirement of how to
* you have to write services. If you
* want to take advantage of the mvc scanners
* (and keep the global scope clean) you should
* use a closure and single top-level namespace.
* In this example we use 'MyApp'
*/
(function($, $Web, $S){
$C.Hello = function(options){
$.extend(true, this, options);
};
$.extend($C.Hello.prototype, new $Web.Servlet(),{
handleGet: function(request, response){
//event handling code here
}
});
})(jQuery, Claypool.Server, MyApp.Service);
This is a good lazy service because it doesn't actively do anything when the anonymous closure is executed other than define itself.
Lets dive in.
handleGet: function(request, response){
$.$('#pizzaModel').order( // order the pizza via synchronous ajax
response.params(), // (mmm hamburger)
function(model){ // ajax callback from model
// we can write directly to the response!
response.body = _.js2json(model);
$.extend(response.headers, {
"Content-Type" : "text/json",
status : 200
})
});
});
}
OMG! How jquery-ish! indeed. To learn more just dive in!
Get ready for a little e4x...
handleGet:function(request, response){
var collections = Xmldb.defaultCollections();
response.
m('collections',collections).
v('.feed').
render();
}
defaultCollections:function(url, callback){
var _this = this;
if (!cache[url]) {
cache[url] = [];
$.ajax({
async:false,
type: 'GET',
url: url,
dataType: 'text',
success: function(result){
result = new XML(result);
for each (var collection in result.*::collection.*::collection ){
cache[url].push({
name: url+'/'+collection.@name .toString() ,
created: collection.@created .toString() ,
owner: collection.@owner .toString() ,
group: collection.@group .toString() ,
permissions: collection.@permissions .toString()
});
}
}
});
}
if($.isFunction(callback)){
callback(cache[url]);
}
}
feed : function(model){
this.$log.debug("Rendering ATOM Response");
// When mvc flows are resolved for Services,
// the view call is decorated with an additional
// 'writer'. The writer has two methods,
// 'write' which is used to fill out the response
// body, and 'append' which appends to it.
var e4x = _.e4x("atom/collections.js", model, true);
/* Thats so cool.*/
this.write( e4x );
}
//the template 'atom/collections.js'
{extend('atom/base.js')}
<block id='entries'>
{_('.*[*]', model.collections).map({
entry: {
title: this.name,
link:{ $href: "#/collections/"+this.name },
id: this.name+'-'+this.owner+'-'+this.group+'-'+this.created,
updated: this.created
summary:{ $type:'xhtml',
p:[ "name: " + this.name ,
"created: " +this.created ,
"owner: " +this.owner ,
"group: " +this.group ,
"permissions: " +this.permissions ]
}
}
}).e4x()}
</block>