Why Use Iowa?
Because it makes even complex web applications easy to write and easy to maintains and because it has been in active production use for over 2.5 years across a wide variety of business applications. The shortest way to illustrate this is to put together a simple, useful example application. Following the example will be a link to a live demo of this very application shown below.
Many web sites feature a guestbook application. This is a simple little application where visitors can sign their name and leave a short message on the site. The code below will show a simple implementation for a guestbook. The guestbook will show a list of entries sorted by the date and time that they were made. Entries disallow any HTML in their bodies. The entries are assumed to be stored in a MySQL database, and the Kansas library is being used for the database operations.
First, here's the definition of our database table:
create table guests (idx int unsigned not null auto_increment primary key,name varchar(255) not null,email varchar(255),entered datetime not null,comment text)
Next we need our stub file to start the Iowa application process; guestbook.rb:
#!/usr/local/bin/rubyrequire 'iowa'require 'iowa/DbPool'require 'kansas'class MySession < Iowa::Sessiondef initialize(*args)######// One can setup special per/session objects or data items here.#// For the guestbook we don't need any, however.#####superendendclass MyApplication < Iowa::Applicationattr_accessor :dbpooldef initialize(*args)######// Initialize the application wide database connection pool.#####@dbpool = Iowa::DbPool.new('Mysql','localhost','demodb','demouser','blahblahblah',2,300) {|dbh|# This block takes the database handles that the connection pool# creates and turns them into Kansas database handles.ksdbh = KSDatabase.new(dbh)unless defined?(@@ks_done_init)@@ks_done_init = trueksdbh.map_all_tablesendksdbh}superendendIowa.startDaemon('guestbook.cnf')Iowa.run
Next, the configuration file for the stub; guestbook.cnf:
socket:hostname: localhostport: 9988logging:basedir: /var/log/iowa/guestbookminlevel: 0maxsize: 10000000maxage: 86400
That's all of the boilerplate necessary to support the Iowa application. Most of the time the stub file and the configuration file are just copied from the template file and then modified slightly to accomodate the needs of the particular application. Everything after this is the HTML and the code for this very simple guestbook application.
Main.html -- the HTML for the main display:
<html><head><title>Guestbook</title><head><body><h1 align="center">Guestbook</h1><br/><p><a oid="make_entry">Make an entry in the guest book!</a></p><repeat oid="entry_list"><br/><b>Name:</b><if oid="has_email?"><a href="mailto: @entry.email">@entry.name</a></if><unless oid="has_email?">@entry.name</unless><br/><b>Date Entered:</b>@entry.entered<br/>@entry.comment<hr/></repeat></body></html>
And the code for the main display; Main.iwa:
class Main < Iowa::Componentattr_accessor :entrydef has_email?@entry.email.to_s != ''enddef make_entrynewPage = pageNamed('Entry')yield newPageenddef entriesresult = nilapplication.dbpool.getConnection do |ksdbh|result = ksdbh.select(:Guests) {|g| g.sort_by('Entered' => 'desc')}endresultendend<?entry_list {item = entrylist = entries}
This guestbook application has one other page, the page where one makes a new entry into the guestbook. This page will take some user input, validate it, deliver an error message if there is a problem, and if there is no problem it will save the entry into the database and then return to the main display page.
Entry.html -- The page to make a new entry to the guestbook:
<html><head><title>Guestbook Entry</title><head><body><h1 align="center">Guestbook Entry</h1><br/><p>Fill in the fields below and press the <em>Save Entry</em> buttonto save your entry into the guestbook. The <em>Email</em> field is optional.Please do not use any HTML in your entry.</p><form oid="saveEntry"><if oid="err"><p style="color: #d40026">Error; A name must be provided.</p></if>Name: <input type="text" oid="name" size="40" maxlength="255"><br/>Email: <input type="text" oid="email" size="40" maxlength="255"><br/>Comments:<br/><textarea oid="comment" rows="3" cols="65"/><br/><input type="submit" oid="cancel" value="Cancel"> <input type="submit" oid="save_entry" value="Save Entry"></form></body></html>
Entry.iwa -- The code for the entry page:
class Entry < Iowa::Componentattr_accessor :err, :guest_name, :email, :commentdef awake@comment = ''enddef cancelnewPage = pageNamed('Main')yield newPageenddef save_entry@guest_name = @guest_name.gsub('<','<').gsub('>','>')@err = @guest_name.to_s != '' ? false : trueunless @err@email = @email.gsub('<','<').gsub('>','>')@comment = @comment.gsub('<','<').gsub('>','>')application.dbpool.getConnection do |ksdbh|ksdbh.new_object(:Guests)entry = ksdbh.select(:Guests) {|g| g.idx = g._last_insert_id()}.firstentry.name = @guest_nameentry.email = @emailentry.entered = Time.now.strftime('%y/%m/%d %H:%M:%S')entry.comment = @commentendnewPage = pageNamed('Main')yield newPageendendend
That's it. It's an ugly but functional guestbook application. The HTML is cleanly seperated from the code while still leaving the special markup within the content obvious and understandable enough that a designer could easily edit the HTML file to improve the look for the guestbook without having to worry about breaking the application, and the developer could easily alter the code without having to worry about wading through content generation code or accidentally breaking content generation code.
The live demo of this guestbook can be found here: Guestbook
Last Modified: $Date: 2004/10/19 19:44:39 $


