Explicit Primary Key with ActiveRecord

If you need to use an explicit primary key and not an AUTO_INCREMENT with ActiveRecord I wrote this snippet that has proved very handy:

module ExplicitPrimaryKey
  attr_accessor :pk
  def before_create; self.id = pk; end
end

Then when you call the create method supply :pk => value along with the other values.

ActiveRecord is an ORM solution that grew out of Ruby on Rails. It is entirely separate and can be used outside of Rails.

Non-Text-Based Programming and Picking Examples

Very interesting video about the non-text-based programming environment subtext. You can go watch the video, I’ll still be here.

I had to have a quick go at a better version of the Java program that he is improving.

He uses:

    enum Attack { Magic, Melee }
    int damage (Attack attack, bool surprise, int defense) {
        int power;
        switch (attack) {
            case Magic:
                power = 5;
                break;
            case Melee:
                power = 4;
                break;
        }
        int effectiveness = power * (surprise ? 3 : 2);
        switch (attack) {
            case Magic:
                if (effectiveness >= defense)
                    return effectiveness - defense;
                return 0;
            case Melee:
                return (effectiveness / defense) * 2;
        }
    }

Which isn’t actually legal java but it’s close enough.

But how about:

    enum Attack { MAGIC, MELEE }
    int damage (Attack attack, boolean surprise, int defense) {
        int m = (surprise ? 3 : 2);
        if (attack == Attack.MAGIC) {
            return Math.max(5 * m - defense, 0);
        } else {
            return ((4 * m) / defense) * 2;
        }
    }

Which reduces 21 lines to 9. It also gets rid of the main complaint – the “traffic jam” in the middle (but see Update, below).

Or even:

    enum Attack { MAGIC, MELEE }
    int damage (Attack attack, boolean surprise, int defense) {
       int m = (surprise ? 3 : 2);
       return (attack == Attack.MAGIC ? Math.max(5 * m - defense, 0) : ((4 * m) / defense) * 2);
   }

Which is pretty cryptic but only 5 lines.

I think it was a very interesting video and I’m being a bit unfair harping on about this which is kind of irrelevant. But perhaps there’s a lesson in there about picking examples. Conclude what thou wilt.

Would love to have a go with the subtext application.

Update I sent my annoying little examples to Jonathan Edwards who is the creator of subtext. He made some good points in reply (and helped me remove a redundant assertion in my code):

Thanks for your comments. Your revision avoids duplicating the switch by duplicating the multiplication operation. Imagine that single multiplication being instead 10 lines of code. One could of course then push it into a separate method which is called twice, at the cost of separating that code from its uses, and passing as arguments all the dependencies of that code. These are all reasonable trade offs. I am trying to reduce the need to make such trade offs, and keep the code simpler and more compact.

Steven Pinker at Congress Centre

Great talk taken from his new book The Stuff of Thought. I won’t cover the sophisticated and interesting arguments here (read the book!) but here are some nuggets on use of language …

Box of crayons that looks like an audience because it is in rows and tiered

Child to her father:

I don’t want the flat crayons I want the ones that look like an audience.

Groucho Marx classics:

I’ve had a great evening. But this wasn’t it.

If I held you any closer I’d be on the other side of you.

Why does a man with hair on his head have more hair than a man with hairs on his head?

Was the World Trade Centre attack on September 11th 2001 one incident or two? There was a 3.5 billion dollar lawsuit based on the interpretation of a maximum payout of $3.5 billion dollars “per incident”.

One of the reasons detectives suspected Scott Peterson of the murder of his wife was that he referred to her in the past tense before her body was found.

James Garfield‘s assassin’s remark following the death of the President of the United States from complications arising from poor medical care after being shot three months earlier:

The doctors killed him. I just shot him.

The Federal Communications Comission chose not to censure Bono over his remark that the award he was receiving was “really, really fucking brilliant” as it did not refer to a sexual act but was rather used to emphasize. Further legislation was passed as a result of this. Although the legislation goes into graphic detail over what words are not allowed it fails to make illegal the use of fucking as an emphasizing adverb.

That “damn tabernacle” and “damn chalice” are swearing in Quebecois French.

The description of a certain mode of speech as “fuck patois”. And an illustrative tirade from a soldier returning from war:

You fucking mean I’ve fucking come all the way fucking home from the fucking war to my fucking house to find my fucking wife having illicit sexual relations with my fucking neighbour?

The editor of Gourmet magazine challenged one of his journalists to bribe the maître d’s of New York’s finest restaurants $50 to seat him and his partner without reservations. It worked each and every time.

Simple Haskell Web Programming with HAppS

Motivation

There are two or three CGI libraries for Haskell. But if you ask the cognoscenti (to be found on the #haskell IRC channel) for Haskell web programming recommendations they will almost invariably point you at HAppS.

HAppS may have many virtues but it’s documentation and associated tutorial do not number among them.

Copying the first Rails screencast, Creating a Blog in Fifteen Minutes, I figured that a good example web application is a blogging system. Leaving aside that blogging is now pass�, here is my HAppS tutorial.

Please note that I am a fairly inexperienced Haskell programmer and almost all the advice I give will be wrong. Some of what I say will necessarily be vague because I don’t understand it completely myself. But the advantage to my tutorial is that it will at least be comprehensible! I hope that some Haskell gurus will read this and find my mistakes and update me in the comments. Thanks!

Installation

For installation of HAppS, please see my earlier post.

Hello, World

First, let’s get HAppS working and see something in our browser. Save the following listing to Hello.hs:

import HAppS
import HAppS.Protocols.SimpleHTTP2
 
main = stdHTTP [debugFilter, noState, h () GET $ ok $ val "Hello, World"]

If you compile that with:

ghc --make Hello.hs -o hello

And then run the resulting “hello” binary (./hello under Unix, hello under Windows). If you visit http://localhost:8000/ in your browser you should see “Hello, World” displayed.

So what have we actually done there? Well, I don’t really know. But certainly we’ve passed a list of directives to the stdHTTP function. One of which (the bit starting “h”) says: “if you get a GET request of any sort, respond with a page containing the text ‘Hello, World'”. Let’s just leave it at that for now.

Blog System

Weren’t we meant to building a blogging system? Yes! OK, let’s start with the URL scheme. We want the following paths in our system:

GET  /new 		=> Show the "create new post" form
POST /new	 	=> Create a new post using the submitted values
GET /post/$id 	=> Display the post with id $id
GET /			=> Dispaly the last 5 posts

The way to describe this scheme to HAppS is through the first and second arguments to the h request-handling function. The first argument is the path as a list (each element in the list representing a directory) and the second argument is the type of request (GET, POST and so on). So for displaying the “create new post form” we use h ["new"] GET.

Our GET /post/$id path is slightly tricky in that we don’t want to write out a very long list of post ids. We want to do some pattern matching. You can do this in HAppS with the re function. This tells HAppS to interpret the paths in the list as regular expressions. So for GET /post/$id we can use h ["post", "(0-9 )"] GET.

Putting that all together gives us:

import HAppS
import HAppS.Protocols.SimpleHTTP2
 
main = stdHTTP $ debugFilter : noState : 
           [h ["new"]                           GET  $ ok $ val "Show create post form"
           ,h ["new"]                           POST $ ok $ val "Save post and forward to display post"
           ,h (re ["post", "([0-9] )"])  GET  $ ok $ \\(id:_) () -> respond ("Display post "    id)
           ,h [""]                              GET  $ ok $ val "Display five most recent posts"
           ]

HTML in Haskell

Those calls to val are just placeholders. What we really want to return is some HTML.

The most common way to get HTML in Haskell seems to be to use one of the HTML combinator libraries such as Text.XHTL.Strict. This is only tangentially related to HAppS so I’ll just point you at this simple example and these fairly comprehensible notes and move on.

Now we have:

import HAppS
import HAppS.Protocols.SimpleHTTP2
import Text.XHtml.Strict

main :: IO ()
main = stdHTTP $ debugFilter : noState : 
           [h ["new"]                           GET  $ ok $ val showCreatePostPage
           ,h ["new"]                           POST $ ok $ val "Save post and forward to display post"
           ,h (re ["post", "([0-9] )"])  GET  $ ok $ \\(id:_) () -> respond ("Display post "    id)
           ,h [""]                              GET  $ ok $ val "Display five most recent posts"
           ]

-- Handlers

showCreatePostPage :: String
showCreatePostPage = showHtml getCreatePostPage

-- HTML Functions

getCreatePostPage :: Html
getCreatePostPage = mkHeader "New Post"
        body < < [
        (h1 << "New Post") 
            getCreatePostForm
        ]

getCreatePostForm :: Html
getCreatePostForm = (form ! [action "/new", method "post"] << (fieldset << [
        label ! [thefor "title"] << "Post Title", br,
        input ! [name "title", identifier "title", thetype "text"], br, br,
        label ! [thefor "body"] << "Post Body", br,
        textarea ! [name "body", identifier "body", rows "10", cols "40"] << "", br, br,
        submit "create" "Create Post"
    ]))

mkHeader :: String -> Html
mkHeader title = (header < < (thetitle << (title    " - HBlog")))

State

Of course I've chickened out above. Yes, I've provided some HTML that never changes. But what about the pages that depend on state? What about the display of the posts themselves? It's time to get rid of that odd-looking noState directive and start storing some blog posts. This is where it gets a little bit hairy.

While you could use a relational database with HAppS, it actually has it's own in-built haskell type-based storage system. It has lots of whizzy features that I'm not concerned about here to do with atomicicity and all that kind of shenanigans. But let's stay focused - we need a way of storing some blog posts. That means we need to define a type that derives Show and Read.

data Posts = Posts [Post] deriving (Read, Show) 
data Post = Post { pTitle :: String, pBody :: String } deriving (Read, Show)

What’s more we have to give it some instances so that HAppS can start it up, and know how to store it.

instance Serialize Posts where 
    typeString _ = "Posts"
    encodeStringM = defaultEncodeStringM
    decodeStringM = defaultDecodeStringM

instance StartState Posts where
    startStateM = return $ Posts []

OK, so now we know where we are going to store our posts. But how do we construct them in the first place? Well, Post is a record type, I will assume you know how to use record types. But what about extracting the values from the post body to slot into the record?

Strings we can get with:

v < - lookMb return req "fieldName"

where req is the Request, the second parameter passed to the function after ok in our request handlers. This code must appear in a do block.

Ints we can get with:

v < - lookMb readM req "fieldName"

Quite what the meaning of this distinction is, I don't know. So please leave a comment if you understand this better than me.

The state of the application itself (in our case a Posts, or list of Post) you can retrieve with get and update with put as long as you are within the appropriate Monad. This probably makes more sense in the context of a full example:

module Main where

import Control.Monad.State (get, put)
import Debug.Trace
import HAppS
import HAppS.Protocols.SimpleHTTP2
import Text.XHtml.Strict

main :: IO ()
main = stdHTTP $ debugFilter : 
           [h ["new"]                           GET  $ ok $ val showCreatePostPage
           ,h ["new"]                           POST $ ok createPost
           ,h (re ["post", "([0-9] )"])         GET  $ ok showPost
           ,h [""]                              GET  $ ok showPosts
           ]

-- State

data Posts = Posts [Post] deriving (Read, Show) 
data Post = Post { pTitle :: String, pBody :: String } deriving (Read, Show)

instance Serialize Posts where 
    typeString _ = "Posts"
    encodeStringM = defaultEncodeStringM
    decodeStringM = defaultDecodeStringM

instance StartState Posts where
    startStateM = return $ Posts []

-- Handlers

showCreatePostPage = showHtml getCreatePostPage

showPost (rawId:_) () = do
    (Posts posts) < - get
    let postId = read rawId :: Int
        post = posts !! postId 
    respond $ showHtml $ getPostsHtml [post]

showPosts () () = do
    (Posts posts) <- get
    respond $ showHtml $ getPostsHtml $ take 5 $ reverse posts 

createPost () req = do
    title <- lookMb return req "title"
    body  <- lookMb return req "body"
    let p = Post { pTitle = title, pBody = body }
    (Posts ps) <- get
    put (Posts (ps    [p]))
    respond $ "Post created"

-- HTML Functions

getCreatePostPage :: Html
getCreatePostPage = mkHeader "New Post"
        body << [
        (h1 << "New Post") 
            getCreatePostForm
        ]

getCreatePostForm :: Html
getCreatePostForm = (form ! [action "/new", method "post"] << (fieldset << [
        label ! [thefor "title"] << "Post Title", br,
        textfield "title", br, br,
        label ! [thefor "body"] << "Post Body", br,
        textarea ! [name "body", identifier "body", rows "10", cols "40"] << "", br, br,
        submit "create" "Create Post"
    ]))

getPostsHtml :: [Post] -> Html
getPostsHtml posts = foldl (   ) noHtml (map getPostHtml posts)

getPostHtml :: Post -> Html
getPostHtml post = 
    thediv 
        < < h2 << (pTitle post)
            p << (pBody post)

mkHeader :: String -> Html
mkHeader title = (header < < (thetitle << (title    " - HBlog")))

Once your HAppS application has state then wherever you run it it will create directories to store state information. If you change your state type, you must delete these directories (you will lose existing state of your app) to prevent errors like: *** Exception: user error (decodeStringM: parsing length field failed @ "").

Conclusion

So there you have a working blog publishing system in HAppS. It's more a proof of concept than a useable application. But hopefully it shows you how to create a simple application in HAppS without boiling your brain too much. There are zillions of improvements that could be made: add comments; make Posts a sequence and not a list; add error handling for empty fields; redirect to post display after creation; handle error when post id is greater than the number of posts; don't number posts starting from 0; allow deletion of posts; and many many others.

I must credit Eric Mertens for his sterling work on HPaste whose source code I read to make sense of much of what HAppS was doing.

Please do correct all my terrible misunderstandings and mistakes in the comments!

How to Install HAppS

Update: these instructions refer to the HAppS, 0.8.8. The latest version (September 2007) if 0.9.1a. It radically alters the HAppS APIs as well as the installation procedure. You can find more information here which is an incomplete tutorial inside one of the new source code repositories.

  1. Get the latest version of ghc for your platform:

    http://haskell.org/ghc/

  2. Get the latest version of darcs:

    http://wiki.darcs.net/DarcsWiki/CategoryBinaries

  3. Throughout, when building HAppS or any of it’s dependencies use:

    $ runhaskell Setup.hs configure
    $ runhaskell Setup.hs build
    $ sudo runhaskell Setup.hs install
    

    and not the makefiles. Even where the README or web page says otherwise. In some instances Setup.lhs will be provided instead of Setup.hs.

  4. Use the latest source for HAppS 0.8.8 not the stable version. The stable version won’t build! Get it via darcs not tarballs. The tarballs are broken links!

    darcs get --partial http://happs.org/HAppS
    
  5. Try and build HAppS (with the commands in step 3 above), and every time you fail, install the missing packages. The documentation in the HAppS tutorial is up-to-date (as of September 2007) on this score. So you may be better off there than here if it is long after that date.

    The hackage package list is useful but not complete.

    You may need: HaXML, binary, hslogger.

    HList is a special case as it doesn’t have a conveniently downloadable package. Use:

    wget -r -nH -X '*/_darcs' -np http://darcs.haskell.org/HList/
    

    Plus the following are only available via darcs: syb-with-class ( darcs get http://happs.org/HAppS/syb-with-class ), default ( darcs get http://happs.org/HAppS/default ), normalize ( darcs get http://happs.org/HAppS/normalize ), generic-xml ( darcs get http://happs.org/HAppS/generic-xml )

You can test your installation with the “Hello World” in the HAppS Tutorial

Update: the rest of the HAppS tutorial was fairly dense and difficult to understand as well as being somewhat out of date. To remedy this situation I wrote Simple Haskell Web Programming with HAppS.

Prevent Browser Caching

You can’t force a browser (or other User Agent) to do anything. You must carefully implement your server side code to prevent malicious or accidental damage. That said, you can sometimes improve the user experience a lot by asking browsers nicely not to cache anything and thus to request the page again when (amongst other things) the Back button is used.

You can do this with the following HTTP headers. (Note: This doesn’t work on Opera as it does on other browsers.)

Cache-Control: no-cache
Cache-Control: no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache

In PHP you can do this with:

header("Cache-Control: no-cache");  // Forces caches to obtain a new copy of the page from the origin server
header("Cache-Control: no-store");  // Directs caches not to store the page under any circumstance
header("Expires: " . date('D, d M Y H:i:s', 0) . ' GMT'); //Causes the proxy cache to see the page as "stale"
header("Pragma: no-cache");         // HTTP 1.0 backward compatibility

This is not the perfect solution. If the browser ignores these headers (as Opera will – see comments) then you can still go back and see stale pages. I wonder what banks do to get around this where the viewing of a stale page can be considered a security breach?