These days it seems like everybody and their dog wants to create something like Ruby on Rails. While there are a number of competitors out there, the only one I have any experience with is Catalyst, written in Perl. I had a commit bit on that project once and it looks really promising, but it’s “some assembly required” (or at least, it was last time I checked). It has an overwhelming number of options and tries very hard to not tie your hands at all. It has a great dispatching action, but in the end, if you’re new to Catalyst, or worse, new to Perl, the number of different options and how to hook them together can seem daunting. Once you get them working, though, Catalyst is pretty fun.
For various reasons, I’ve moved on from that project, but the idea of “just get it done” is very appealing to me. Since I’m primarily a Perl programmer nowadays, when I saw that Jifty had been released, I was pretty excited. I know Jifty’s primary architect, Jesse Vincent, and have a lot of respect for him, so that helped me be excited even though Jifty is yet another web application framework. (It’s also worth noting that Jifty is put out by the makers of RT, a very popular request tracker, so these folks know a good thing or two about progamming.) However, Jesse might not like me mentioning Rails and Jifty in the same blog post since Rails isn’t even mentioned in the Jifty docs. To be fair, Jifty is not a port of Rails and doesn’t pretend to be. It’s just your basic AJAXified full-stack continuation-based Web Application Platform. Hmm, how can I make this not boring? I know, I’ll write this blog entry while I work through the tutorial. Something has to break, I’m going to do something stupid, or some other problem will arise.
Installing Jifty
Let’s see, Jifty depends on over 60 modules from the CPAN. This is going to be a nightmare to install. I first tried installing Jifty a couple of days after it came out and it installed fine, but I couldn’t get it to work, so I have a bit of trepidation here (plus, I like Jesse, so if something fails while I’m writing this, I don’t want to make him look bad).
cpanp -i Jifty
Wow. I had most of them installed already. In fact, there were only four other modules I needed:
- Object::Declare
- PAR::Dist::FromCPAN
- Scalar::Defer
- JSON::Syck
Of course, I’m kind of a Perl power user, so it’s quite possible you’ll have more uninstalled dependencies. Still, those four modules installed without a hitch and then the Jifty install went smoothly (note, if you’ve not used cpanp, it’s the command line script for CPANPLUS and it installed the four modules automatically, after asking if it was OK. There was no other work on my part other than typing “yes”).
Creating my first model.
So I start the tutorial.
jifty app –name MyWeblog
Look familiar? That creates the shell of your application. I cd MyWeblog/ and look around. The first thing I notice is that web/static/ doesn’t exist, even though it’s listed in the tutorial. Turns out it’s in share/web/static/. Ah well, I’m used to subtle discrepancies in docs. So I start creating my weblog
The first thing I need to do is post to my weblog, so I create a model for it.
jifty model –name Post
Hmm, I see that it also created a t/00-module-Post.t. It’s probably just a test to make sure I can load my model, but even though the docs don’t list this, I go ahead and run it.
MyWeblog $ prove -lv t t/00-model-Post....1..11 ok 1 - use MyWeblog::Model::Post; ok 2 - Found a system user ok 3 - Post create returned success ok 4 - New Post has valid id set ok 5 - Create returned the right id ok 6 - Post create returned another value ok 7 - And it is different from the previous one ok 8 - Finds two records ok 9 - Finds one record with specific id ok 10 - Deleted row is gone ok 11 - Still one left Done. ok All tests successful. Files=1, Tests=11, 6 wallclock secs ( 2.11 cusr + 0.53 csys = 2.64 CPU)
(Those tests might seem slow, but I have some pretty heavyweight processes running in the background for some other work I’m doing).
Whoa! It’s already verifying that my model works, even though I’ve not specified anything. I do a bit of digging around (using Devel::Trace to get a full execution flow dumped to a log) and find out that internally it’s using DBI, the standard database interface, but I want to get back to work and I figure I’ll sort this out later.
Adding a simple schema
I do a quick vim lib/MyWeblog/Model/Post.pm and I add the following lines:
column title =>
type is 'text',
label is 'Title',
default is 'Untitled post';
column body =>
type is 'text',
label is 'Content',
render_as 'Textarea';
Hey, that’s about as declarative as you can get. I like that.
So now it’s time to open up my database and create the tables. Hey, I don’t have to do that!
MyWeblog $ jifty schema --setup INFO - Generating SQL for application MyWeblog... INFO - Using Jifty::Model::Session INFO - Using Jifty::Model::Metadata INFO - Using MyWeblog::Model::Post INFO - Using Jifty::Model::Schema INFO - Set up version v0.0.1, jifty version 0.607220
Well, I’m curious, so I look in the etc/config.yml file to see where the database is and it’s an SQLite database in my current directly, named myweblog. By default, Jifty uses SQLite so you can play with it, but Jifty::Config has the information about how to connect it to other databases such as PostgreSQL or MySQL.
sqlite3 myweblog sqlite> .tables _db_version _jifty_metadata _jifty_sessions posts sqlite> .schema posts CREATE TABLE posts ( id INTEGER PRIMARY KEY NOT NULL , title text DEFAULT 'Untitled post' , body text );
Hey, I didn’t even have to touch the database to create that. Nice.
Running the app
Now it’s time to start the server.
MyWeblog $ ./bin/jifty server INFO - You can connect to your server at http://localhost:8888/
Well, uh, I haven’t created view yet. I wonder what I’m going to get. I go to http://localhost:8888/ and hey, I get a Pony! I also get full online documentation and and administrative console. The adminstrative console already gives me full CRUD (Create, Read, Update, Delete) access to my database. Nice. Jifty comes with its own (slow) Webserver so you can test right away without configuring Apache, IIS, or whatever you use.
I shut the server down and now edit share/web/templates/post (this time the documentation has the path right).
Creating my view
<%init>
my $action = Jifty->web->new_action(class =>'CreatePost');
</%init>
<&|/_elements/wrapper, title => "Post to your weblog" &>
<% Jifty->web->form->start() %>
<% Jifty->web->form->next_page( url => '/') %>
<% $action->form_field('title') %>
<% $action->form_field('body') %>
<% Jifty->web->form->submit( label => 'Post' ) %>
<% Jifty->web->form->end() %>
</&>
Now the Jifty docs diverge. I can create the boring way of listing all of my post entries, or I can create the nifty AJAX way. I’m daring. I’m going for the latter.
vim share/web/templates/index.html
And add this:
<&|/_elements/wrapper, title => Jifty->config->framework('ApplicationName') &>
<% Jifty->web->region(name => "myweblog-posts",
path => "/fragments/page_of_posts") %>
</&>
Side note: If you’re wondering about all of the work to escape HTML entities for this weblog, I have a mapping in my .vimrc to this function:
function! HTMLEscape()
%s/&/\&/g
%s/>/\>/g
%s/</\</g
echo "HTML special characters escaped"
endfunction
And back to the show.
MyWeblog $ mkdir share/web/templates/fragments MyWeblog $ vim share/web/templates/fragments/page_of_posts
<%args>
$page => 1
</%args>
<%init>
my $posts = MyWeblog::Model::PostCollection->new();
$posts->unlimit();
$posts->set_page_info( current_page => $page,
per_page => 25
);
$m->out("No items found.") if ($posts->pager->total_entries == 0);
</%init>
% if ($posts->pager->last_page > 1) {
Page <% $page %> of <% $posts->pager->last_page %>
% }
<dl class="list">
% while (my $post = $posts->next) {
<dt><%$post->title%></dt>
<dd><%$post->body%></dd>
% }
</dl>
% if ($posts->pager->previous_page) {
<% Jifty->web->link( label => "Previous Page", onclick => { args => { page => $posts->pager->previous_page } } ) %>
% }
% if ($posts->pager->next_page) {
<% Jifty->web->link( label => "Next Page", onclick => { args => { page => $posts->pager->next_page } } ) %>
% }
Now it’s time to fire up the Web server again. I’m pretty nervous now because I’m writing this as I go along and I don’t want this to fail, but I’ve done a lot of stuff here and I’m used to stuff failing. But I go to http://localhost:8888/post/ and there’s a post page! I type in a post, hit submit and it tells me I’ve create a post. I click the ‘x’ button on the ‘create’ message and it just fades away, leaving just the post for me.
Adding to the menu
Reading along in the docs, they want me to add “Post” to the navigation menu. OK.
MyWeblog $ mkdir share/web/templates/_elements MyWeblog $ vi share/web/templates/_elements/nav
And I add this:
<%init>
my $top = Jifty->web->navigation;
$top->child( Home => url => "/");
$top->child( Post => url => "/post",
label => "Post Article");
</%init>
I fire up the server again and the admin and documenation links are gone, but there’s my post button. Adding another entry works just fine.
By default, admin mode is ‘on’ and Jifty has a large red bar across the top of the screen letting us know this. I click on its admin link and I’m back at the admin page. From there, I try editing and adding posts and yup, AJAX is working just fine. There doesn’t seem to be a ‘delete’ link, like I wrote earlier, but that’s OK.
Conclusion
Well, that was painless. Everything just worked. That’s what app development should be. After I wrote this, I browsed through the docs a bit more and they are definitely a work in progress. Not everything was as obvious as it should be and some things didn’t work (jifty schema –man, for example). Also, even though the default text was telling me that column declaration syntax was in Jifty::DBI::Schema, I accidentally used the syntax shown in Jifty::Param::Schema and Jifty built a database, and the checkbox got rendered as a regular text input box. Once I consulted the right docs (perldoc Jifty::DBI::Schema), it worked just fine. Given how young this framework is, I’m pleasantly surprised.
I’m sure some of you are thinking “that was stupid. Why should he be pleased about that? Rails already does all that and more.” This is true, but if you’re in a Perl shop and your company doesn’t want other languages used (this is very common), then having a good Perl alternative is nice and I’m quite happy to see this on here. Catalyst is also nice, but I’m keen to see what Jifty is going to do.
If you really want to see Jifty in action, check out Hiveminder. It’s a ridiculously easy to use task manager (oh, and free, too).


After reading this article I gave Jifty a try too. Very nice indeed. I absolutely love the easy model setup :)
The only thing I don't like so far is the mixing of markup and programming in the templates (and the Mason syntax is making my eyes bleed).
Sadness! I wanted to try also but ...
$ cpanp -i Jifty
Installing Jifty
WARNING: This key is not certified with a trusted signature!
Primary key fingerprint: AB4A 62CF 1A1A 119A 0462 39D6 122F 5DF7 108E 4046
Not in MANIFEST: doc/._jifty-dispatcher.graffle
==> MISMATCHED content between MANIFEST and distribution files! <==
[ERROR] Signature check failed for module 'Jifty' -- Not trusting this module, aborting install
Error installing 'Jifty'
Problem installing one or more modules
-----------------------------------------------
I had to build and install Jifty by hand. How archaic ;-)
I recently tried out Jifty and decided I was not ready to use it for anything real (awesome name though). Here are my main complaints.
1. Had a hard time installing. Didn't try CPANPLUS, though.
2. I was getting a rather cryptic error message when trying to customize the tutorial templates. Turned out to be the $m I had created. Apparently $m is used for the Mason handle, or something. Bad form, IMO.
3. The automatic creation of *Collection modules bothered me somehow. Just a little too AutoMagical, for my tastes I guess.
4. I wanted to do nifty stuff like Autocomplete but couldn't find any understandable documentation.
Inspired by perlcast i would have liked to try out WebGUI from plainblack. On OS X i was unfortunatly unable to install it with the wre.
I tried out ***** "ready to use" for OS X and was up and running in no time.
I would readily go back to perl but for the time being things seem to be simpler and faster with other solutions. Especially for the installation/configuration department.
And i hate to say that.
Furthermore i don't like that "the other guys" will be on the standard installation of leopard, while "we" will have to struggle to even install an up to date version of the basic language.
Liked the model setup too.
The installation was "somewhat painfull" :-(
The documentation was "somewhat lacking" :-|
Concerning the Mason templating... well.. the less said the better!
All in all an interesting project but not quite ready for prime time.