For consultancy services : tech@damianhelme.com


Bootstrap Navbar Dropdowns and Lift's Menu Builder 2012-02-13

Here's announcing a little utility I wrote to convert Lift's Menu.builder output into a nav bar with drop downs styled with Twitter's Bootstrap libraries.

Using this utility it's easy to generate a nav bar from your SiteMap that looks like:

In particular, the features I'm looking to recreate here are:

  • The nav-bar sits at the top, with the user navigation options (e.g. Login, logout, etc) and held over to the right. Once the user is logged in the Logout, Change Password, etc options are on a drop-down menu whose root value is the name of the logged-in user.
  • The man nav options are held over the the left.
  • An arbitrary number of the main nav options may be menu drop-downs and are easily configured using SiteMap 'submenu's

The utility is available to download https://github.com/dph01/lift-TBUtils

An example project using the library is available for download here: https://github.com/dph01/lift-TBNavbarTemplate

You can see a running version of this application at www.damianhelme.com/tbnav

To create this nav bar, the menus are defined in Boot.scala by:

DIY Lift CRUD - an alternative to CRUDify 2012-07-21

This article describes a simple approach for creating your own CRUD (Create, Read, Update, Delete) database screens in Lift.

Why build your own CRUD screens?

Lift has a useful trait, CRUDify, that automatically adds CRUD functionality to any class.
CRUDify is useful for rapid prototyping and can even be deployed to production where basic functionality is sufficient.

You can customise much of the default behaviour by overriding the CRUDify methods. However, there is a practical limit to how far you can go with the customisation.

When your requirements diverge too much from the default CRUDify functionality, you can easily find yourself trying to coerce CRUDify to perform in ways in which it was not designed to perform. This can quickly lead to bloated, convoluted code that is hard to maintain. At this point it is often easier to abandon CRUDify and write your CRUD screens from the ground up.

What is covered?

This article describes a simple approach for implementing a customised CRUD application.
It covers how to organise your application into folders, files, classes, and methods. A naming convention is provided for these artifacts as well as a simple model illustrating allowable screen transitions.

Joel Spolsky & Stack Exchange 2012-02-22

Went to an interesting talk this week at Cambridge Network - Joel Spolsky from Stack Exchange, Joel on Software, etc fame. Stack Exchange has 20 million unique visitors per month, only 50 employees & Google use Stack Overflow as a benchmark: it isn't allowed to slip down the rankings after an algo tweak. Nice position to be in!

Scala SBT Template 2012-02-15

Just posted a lightweight template to github for getting started with Scala & SBT: github.com/dph01/scala-sbt-template

It includes sbt-eclipse and templates for ScalaTest.

Understanding Lift's RequestVar 2012-03-01

This post aims to answer some of the questions I originally struggled with when I started using RequestVar's. I think I've got to grips with them sufficiently to help others who are wrestling with the same issue :-). So, here's my contribution to the Lift corpus ...

Consider the common use case, whereby when the user submits a form, if the data fails validation, the data entered is re-presented to the user for correction. The following common pattern meets this requirement by using a RequestVar to hold the state of the submitted data between requests.

The snippet:

class NameSnippet {

  object nameRV extends RequestVar("")                // 1

  def processSubmit() = {
    // perform some simple validation
    if (nameRV.is.length < 3) 
      S.error("event name must be at least 3 characters")
    else {
      S.notice("name OK")
      S.redirectTo("/")
    }
  }

  def render = {
    "#name" #> SHtml.text(nameRV.is, x => nameRV(x) ) & // 2
    "#submit" #> SHtml.onSubmitUnit(processSubmit)      // 3
  }
}