Friday, March 10, 2006

So Sweet with Ruby

The Ruby programming language can be so sweet. (Ok, this is a bit off-topic, but still cool Web development subject.) I wanted to do some custom Web log analysis recently using Ruby, and it just came out so nicely, a clean object-oriented class in no more than ten lines of code, and a trivial filter. Ruby Structs, regular expressions, and language conveniences to the rescue! I just had to put it on display.

First, a Struct named WebLog to contain the data from the regular expression match:

Struct.new("WebLog", :all, :host, :ident, :user, :time_string,
           :method, :url, :http, :stat, :size, :ref, :ua)
This defines accessors for each named field so you can use it rather like a C struct, e.g. log.host, log.stat.

Then a subclass, with the regular expression tucked away in a class variable. (This RegExp expects "combined" log format.)

class WebLog < Struct::WebLog
  #  host  ident user   time      method url  http   stat  size ref       ua
  @@expr =
   /^(.*?) (.*?) (.*?) \[(.*?)\] "(.*?) (.*?) (.*?)" (.*?) (.*?) "(.*?)" "(.*?)"$/

  def initialize(line)
    super(*@@expr.match(line))
  end
end

The initialize method runs as part of every call to WebLog.new. It calls super, which invokes the Struct::WebLog initializer, and passes all of the match data resulting for the given line. The result is an object with the match data parsed into field.

In the code, @@expr means a class variable named expr, shared by all instances of the class. The result of @@expr.match works like an array: the superclass initialize method expects arguments for each member of the struct, and the * operator in a method call unpacks any array-like structure into an argument list.

The rest of the code runs a custom log analysis. ARGF contains all the lines of all the files on the command line, or if none are give it contains all the lines of standard input. This creates a WebLog object for each line and prints its user agent string (ua). How much neater could it be?

ARGF.each do |line|
  matches = WebLog.new(line)
  puts matches.ua
end

Tuesday, March 07, 2006

Animated Reveal Effects

Power and rich content can also mean clutter. Hiding some of the content or power until needed can help minimize clutter, and animation can help to guide the user's attention. Effects that reveal hidden content with animation can be built with the right CSS and JavaScript, even without heavy programming.

It is not strictly necessary to use absolute positioning in all cases, just two nested elements, overflow: hidden and explicit height or width in the outer one. Because of the browser scripting, it was not possible to put the full demonstration into Blogger, but there are two versions at:

http://perdues.com/iwp/reveal.html