Sample OCFW application
I’ve decided to code a small OCFW application to make it more clear to me how it would look from user point of view. Some parts of the code below are already in working state, others are nothing more than just a prototypes. You are warned!
#import <Foundation/Foundation.h>
#import <OCFW.h>
#import “BlogHandler.h”
int main (int argc, const char * argv[]) {
// Let’s make a global pool. OCFW makes more of those later on
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// This would be our global request handler
WFRequestHandler* rqHandler = [[WFRequestHandler alloc] init];
// And this one is local handler for blog code
BlogHandler* blog = [[BlogHandler alloc] autorelease];
[rqHandler
registerUrl:@"^media/"
forStaticFiles:@"resources/media"
]; // Registering URL that returns static files via X-SENDFILE
[rqHandler
registerUrl:@"^post/(?P<title>\w+)/$"
forObject:blog
selector:@selector(handlePost ![]()
]; // this one will handle requests for blog posts
[rqHandler
registerUrl:@"^/$"
forObject:blog
selector:@selector(handleIndex ![]()
]; // this for list of 10 latest posts
[rqHandler
registerUrl:@"^about/$"
forSimpleTemplate:@"templates/about.html"
]; // and this will just render a simple template
// Now we create a CGI connection handler
WFConnectionHandler* ioHandler = [[WFCGIConnectionHandler alloc]
initWithArgc:argc
argv:argv
];
// And tell it to handle all the requests (in fact only one in CGI) with
// our rqHandler
[ioHandler handleIncomingRequestsWith:rqHandler];
// Release all the stuff, we’re done
[ioHandler release];
[rqHandler release];
[pool drain];
return 0;
}
This is how a main application code looks like. You see that mapping of request URLs to objects is pretty straightforward. I’ve been thinking about some XMLish config for that thing (so you could change mapping without recompilation), but then decided to make it dynamic only, you’re not really doing to modify that stuff every 5 minutes.
Now for the BlogHandler part. This is the header file:
#import <Foundation/Foundation.h>
#import <OCFW.h>
@interface BlogHandler : NSObject {
}
- (WFResponse*)handlePost:(WFRequest*)request;
- (WFResponse*)handleIndex:(WFRequest*)request;
@end
And here’s the implementation:
#import “BlogHandler.h”
@implementation BlogHandler
- (WFResponse*)handlePost:(WFRequest*)request
{
// Grab a post slug form the URL RegExp match “^post/(?P<title>\w+)/$”
NSString* postName = [request match:@"title"];
// Now get *one* object
NSDictionary* post = [WFORM
getObjectFromModel:@"Post" // from Post model
withFilter:[WFFilter
filterForField:@"title" // WHERE 'title'
operator:WFFILTER_EXACT // =
value:postName // postName
]
];
if(post == nil)
// If we matched nothing, return Http 404
return [WFResponse responseNotFound];
else
// else render template with our dictionary as CTemplate dict
return [WFResponse
responseFromTemplate:@"templates/post.html"
withDict:post
];
}
- (WFResponse*)handleIndex:(WFRequest*)request
{
// Get top 10 posts from DB
NSArray* posts = [WFORM
getObjectsFromModel:@"Post"
withFilter:nil
withLimit:10
];
// Create new CTemplate dict and init it with constant values
CTDictionary* dict = [CTDictionary* dictionary];
[dict setValue:@"Sample Blog" forKey:@"TITLE"];
[dict setValue:@"Vladimir Pouzanov" forKey:@"AUTHOR"];
// For each one post add its dict as “POSTS” section
for (p in posts) {
[dict addSectionDictionary:@"POSTS" fromDictionary:p];
}
// And return it rendered on template
return [WFResponse
responseFromTemplate:@"templates/index.html"
withDict:dict
];
}
@end
The ORM stuff is somewhat abstract, I haven’t done deep investigations in this field yet. Anyways this is the way I’d like to see it.
Here’s a sample “templates/index.html” template:
<html>
<head>
<title>{{TITLE}}</title>
</head>
<body>
<h1>Blog of {{AUTHOR}}</h1>
<ul>
{#POSTS}
<li>
<a href=“{{MORE_URL}}”>{{TITLE}}</a>
</li>
{/POSTS}
</ul>
</body>
</html>
This one looks pretty self-explanatory (if you know how google’s ctemplate works
).