My Dot Files: Dot Aliases

This is the first part of a series in which I'll document the various dotfiles I use to support my work, making it easier and more enjoyable.

I use Git and Rails every day at work. To stop my fingers wearing down I've created short aliases for the most common tasks I need to do.

Stick these in ~/.aliases.

# ~/.aliases
# Record how much I've used various Git commands:
#   http://github.com/icefox/git-achievements
alias git="git-achievements"

# Working with Git
alias g='git'
alias gs='git status'
alias gc='git commit'
alias gca='git commit -a'
alias ga='git add'
alias gco='git checkout'
alias gb='git branch'
alias gm='git merge'
alias gd="git diff"

# Working with Rails
alias s='script/server'
alias c='script/console'
alias m='rake db:migrate'
alias r='rake'

# Open the current directory in TextMate
alias e='mate .'

# Serve the contents of the current directory over HTTP
alias serve="ruby -rwebrick -e\"s = WEBrick::HTTPServer.new(:Port => 3000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start\""

Now source the aliases file from your ~/.profile to use them.

# ~/.profile
for I in aliases; do
  [ -f ~/.$I ] && . ~/.$I
done

An updated command prompt

It's been a while since I added the current Git branch to my command prompt to better aid my development efforts. Since then I've started working with several versions of Ruby and find myself working more frequently in situations where the exit status of the last command is a useful thing to know. I've updated my prompt to look like this:

A screen-shot of my command prompt showing username, hostname, exit code of last command, Ruby interpreter information, current working directory and Git information

To get this I declare $PS1 like this:

# Show the exit code of the last command.
# Idea stolen from @mathie.
function last_exit_code() {
  local code=$?
  if [ $code = 0 ]; then
    printf "$1" $code
  else
    printf "$2" $code
  fi
  return $code
}

# I only want to see the interpreter in the output if I'm not using MRI.
function ruby_version() {
  local i=$(/Users/craig/.rvm/bin/rvm-prompt i)
  case $i in
    ruby) printf "$1" $(/Users/craig/.rvm/bin/rvm-prompt $2) ;;
    *)    printf "$1" $(/Users/craig/.rvm/bin/rvm-prompt $3) ;;
  esac
}

# Show lots of info in the __git_ps1 output.
# Thanks for the info @mathie.
export GIT_PS1_SHOWDIRTYSTATE="true"
export GIT_PS1_SHOWSTASHSTATE="true"
export GIT_PS1_SHOWUNTRACKEDFILES="true"

export PS1='\[\033[01;32m\]\u@\h\[\033[00m\] $(last_exit_code "\[\033[1;32m\]%s\[\033[00m\]" "\[\033[01;31m\]%s\[\033[00m\]") $(ruby_version "\[\033[01;36m\]%s\[\033[00m\]" "v p" "i v p") \[\033[01;34m\]\W\[\033[00m\]$(__git_ps1 "\[\033[01;33m\](%s)\[\033[00m\]")\$ '

A one-line web server in Ruby

Prodded by a tweet, here's how to serve a directory in one line of Ruby:

ruby -rwebrick -e'WEBrick::HTTPServer.new(:Port => 3000, :DocumentRoot => Dir.pwd).start'

Handy for sharing files at a conference, for example.

Installing the MySQL gem on OSX 10.6 (Snow Leopard) with MacPorts MySQL5

Took a while to work this command out. Hopefully it can save someone else some time.

sudo port install mysql5-server
sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

Decoupling Nagios Host and Service check events for fun and profit

Nagios does a pretty good job of watching over my services and hosts, but I want to do a little more with the events it creates – when it checks a service and something is wrong, or when something recovers. In particular I want to give my clients the ability to select at an incredibly high resolution what sort of notifications they get, for what services, how often, and at what level of technical detail. Coupled with this I want to up-sell the services that Xeriom offers – if the disk is getting full or the transfer quota is being consumed so fast that it wont last until the end of the month I want to make it easy to upgrade plans. I’d also like to be able to try out some fun things – iPhone push notifications, SMS gateways, audible alarms, whatever – without worrying that I might destroy Nagios and bring my monitoring setup to its knees.

Message queues are a great way of decoupling systems, moving risk and complexity elsewhere. Nagios shouldn’t have to worry about all of the stuff I want to build around the monitoring system, it should focus just on the core features that I like it for: monitoring my hosts and services.

Luckily, I already have ActiveMQ running for other tasks, writing a STOMP client using SMQueue is pretty trivial, and Nagios has several ways to execute external commands when events happen including the global host and service event handlers. All I need is a command to have Nagios run that’ll accept a bunch of information from Nagios and stick it on the message queue.

Here’s what I came up with:

require 'rubygems'
require 'smqueue'
require 'json'

message = {
  :hostname => ARGV[2],
  :service => ARGV[3],
  :state => ARGV[4],
  :state_type => ARGV[5],
  :state_time => ARGV[6].to_i,
  :attempt => ARGV[7].to_i,
  :max_attempts => ARGV[8].to_i,
  :time_t => Time.now.to_i
}

configuration = {
  :host => ARGV[0],
  :name => ARGV[1],
  :adapter => :StompAdapter
}

broadcast = SMQueue(configuration)
broadcast.put message.to_json, "content-type" => "application/json"

You’ll need Ruby and RubyGems installed. Once you have those, install the script like this:

sudo su -
gem sources -a http://gems.github.com/
gem install seanohalpin-smqueue json --no-ri --no-rdoc
cd /usr/bin
wget http://gist.github.com/raw/306765/2a3e9cbade88b4c6dd430e108bc8a28f95047462/notify-service-by-stomp.rb
chmod +x notify-service-by-stomp.rb
Once it's installed tell Nagios to use it by adding this to your Nagios configuration:
define command {
  command_name notify-service-by-stomp
  command_line /usr/bin/notify-service-by-stomp.rb mq.example.com /topic/foo.bar.baz.quux $HOSTADDRESS$ "$SERVICEDESC$" $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEDURATIONSEC$ $SERVICEATTEMPT$ $MAXSERVICEATTEMPTS$
}

global_service_event_handler=notify-service-by-stomp

Change mq.example.com to be the hostname of your message broker, and /topic/foo.bar.baz.quux to be the topic or queue that you’d like notifications to be sent to. Restart Nagios and you should start receiving notifications on that queue or topic.

If you don’t receive notifications form Nagios very often then a simple way to test that this is working is to attach stompcat – a cat type tool that uses STOMP as a source – to the topic or queue, then send a few test notifications to the same queue by manually running the same command that Nagios would.

Here’s a simple stompcat tool in case you don’t have one handy:

#! /usr/bin/env ruby

# Run me like this:
#
#   ./stompcat.rb mq.example.com /topic/foo.bar.baz.quux
#

require 'rubygems'
require 'smqueue'

configuration = {
  :host => ARGV[0],
  :name => ARGV[1],
  :adapter => :StompAdapter
}

source = SMQueue(configuration)
source.get do |m|
  payload = m.body
  puts ">>> #{payload}"
end

Here’s how to send notifications to the queue or topic:

/usr/bin/notify-service-by-stomp.rb mq.example.com \
  /topic/foo.bar.baz.quux service-host.example.com "SERVICE NAME" \
  WARNING HARD 86492 6 6

If it’s working you should get an entry like this showing up where you’re running the stompcat:

{
  "time_t":1266427384,
  "state":"WARNING",
  "state_type":"HARD",
  "state_time":86492,
  "attempt":6,
  "hostname":"service-host.example.com",
  "max_attempts":6,
  "service":"SERVICE NAME"
}

You should be able to change the stompcat example to perform more complex and interesting actions – looking up clients in a database, sending text messages if an account has enough credit, whatever you fancy. If you come up with something fun, please let me know!

Returning explicitly is slower

My main concern about returning explicitly is readability. It's a very subjective thing, but in general whenever I see an unnecessary return statement my internal WTF counter increments.

Less subjective though, it has been pointed out that returning explicitly is slower.

Benchmarking in Ruby is easy. Here's how:

require 'benchmark'

def explicit
  return "TEST"
end

def implicit
  "TEST"
end

n = 100_000_000
Benchmark.bmbm do |x|
  x.report("Explicit return") { n.times { explicit } }
  x.report("Implicit return") { n.times { implicit } }
end

And here are the results of this particular benchmark:

Rehearsal ---------------------------------------------------
Explicit return  50.380000   0.210000  50.590000 ( 51.000510)
Implicit return  36.200000   0.100000  36.300000 ( 36.454038)
----------------------------------------- total: 86.890000sec

                      user     system      total        real
Explicit return  47.650000   0.070000  47.720000 ( 47.744167)
Implicit return  35.900000   0.070000  35.970000 ( 35.985493)

This shows that while returning explicitly is slower, like the to_proc hack it's not slow enough to matter. You need to return a huge number of times to see any significant difference.

Does this change my mind? No. Returning explicitly is still ugly.

Update: The above benchmark was run on Ruby 1.8.6. Tom Ward has provided similar benchmarks for Ruby 1.8.7, 1.9 and jRuby 1.1.6 (using n = 10,000,000) which show that the cost of explicitly returning on these platforms in negligible. Still ugly though.

The stack trace is precious!

The stack trace is one of the most valuable pieces of information you can have when trying to debug a problem. It tells you what line of code was being run when an error was thrown and gives you an idea of the execution path that lead to that line of code being run.

Quick plea then. Please don't do this:

def foo
  do_something
rescue => e
  puts "Problem: #{e}"
  raise e
end

This will start a new stack trace at raise e. If I rescue this further up the stack there's no indication of where the problem was originally encountered - I just get pointed at your error handling code. Precious information, gone.

Do this instead:

def foo
  do_something
rescue => e
  puts "Problem: #{e}"
  raise
end

Note the lack of argument in the call to raise. This tells Ruby to re-raise the last exception. The stack trace remains intact and debugging can continue unhindered. Glory be!

The truth speaks for itself!

Not just for Ruby this time. This applies to pretty much every programming language under the sun.

Don't use unnecessary control statements to determine whether you want to return true or false.

def foo
  if some_boolean && other_boolean
    return true
  else
    return false
  end
end

You should do this instead:

def foo
  return some_boolean && other_boolean
end

It's very very rare that I ever have to return an explicit true or false. This should be a warning sign.

Of course, in Ruby you don't need to return explicitly so you should do this:

def foo
  some_boolean && other_boolean
end

You don't need to return explicitly!

Ruby returns the value of the last line executed.

Don't do this:

def foo
  value = Foo.first(:conditions => { :label => "bar" })
  return value
end

Do this instead:

def foo
  Foo.first(:conditions => { :label => "bar" })
end

Twitter OAuth authentication using Ruby

Here are the steps involved in using Twitter to authenticate using OAuth... because I wanted this post a few days ago and couldn't find it.

Install the required gems.

sudo gem install json oauth

Set up your application at http://twitter.com/apps. Make sure you choose Browser as your application type and check the box saying that you want to use Twitter for login.

Note that if you make a mistake on the new application form it will default to Client for that application type and uncheck the login box. Make sure you set these correctly!

Here comes the magic. Despite the hugely complicated examples found elsewhere only two actions are required. One sets up the authentication request (the login action) and one handles the authentication being completed (the callback action). If you've used OpenID for authentication before this setup should be pretty familiar.

Your login action will look something like this:

# consumer_key and consumer_secret are from Twitter.
# You'll get them on your application details page.
oauth = OAuth::Consumer.new(consumer_key, consumer_secret,
                             { :site => "http://twitter.com" })

# Ask for a token to make a request
url = "http://whatever.com/login/complete"
request_token = oauth.get_request_token(:oauth_callback => url)

# Take a note of the token and the secret. You'll need these later
session[:token] = request_token.token
session[:secret] = request_token.secret

# Send the user to Twitter to be authenticated
redirect_to request_token.authorize_url

Your callback action will look something like this:

# Your callback action will look something like
# this:
#
# Your callback URL will now get a request that contains an 
# oauth_verifier. Use this and the request token from earlier to 
# construct an access request.
request_token = OAuth::RequestToken.new(oauth, session[:request_token],
                                        session[:request_token_secret])
access_token = request_token.get_access_token(
                 :oauth_verifier => params[:oauth_verifier])

# consumer_key and consumer_secret are from Twitter.
# You'll get them on your application details page.
oauth = OAuth::Consumer.new(consumer_key, consumer_secret,
                             { :site => "http://twitter.com" })

# Get account details from Twitter
response = oauth.request(:get, '/account/verify_credentials.json',
                         access_token, { :scheme => :query_string })

# Then do stuff with the details
user_info = JSON.parse(response.body)
# Like find the person that logged in...
Person.find_by_twitter_id(user_info["id"])

If after implementing this you keep getting 401 Unauthorized errors, check that your application is set to browser mode in the Twitter configuration options.

You don't need to count array offsets by hand!

Working with arrays in Ruby. Don't do this:

index = 0
for item in array
  index += 1
  puts "Item #{index}: #{item.inspect}"
end

Do this instead:

array.each_with_index do |item, index|
  puts "Item #{index}: #{item.inspect}"
end

There are a bunch of handy methods like this. Read the Enumerable documentation and make your code that little bit more readable.

A Starling Adapter for SMQueue

Starling is a persistent, lightweight work queue implemented in Ruby which talks the memcache protocol. I've recently started playing with it because I don't have the resource to look after, or the requirement for, a full blown service bus. Starling is easier to install and configure than ActiveMQ, but it's nowhere near as fully featured. Both have their place but a discussion of when and where to use them is outside the scope of this article.

I knew that I wanted to use a message bus to turn synchronous requests into asynchronous requests, pushing work off to some background process somewhere. What I didn't know was the form that the message bus would take. If you're familiar with the Gang of Four patterns book you've probably picked out the pattern that I should use here, but to be honest I'm buggered if I know what it's called. SMQueue which I'm familiar with provides a nice abstraction that makes it easy to swap out the message bus implementation while the code remains identical. Lovely, but SMQueue doesn't come with an adaptor for Starling.

"How hard," thought I, "would it be to implement a Starling adapter for SMQueue?"

I blinked and suddenly it existed. Awesome.

require 'rubygems'
require 'smqueue'
require 'starling'
require 'yaml'

module BarkingIguana
  module Messaging
    module SMQueue
      class StarlingAdapter < ::SMQueue::Adapter
        class Configuration < ::SMQueue::AdapterConfiguration
          DEFAULT_SERVER = '127.0.0.1:22122'

          has :queue
          has :server, :default => DEFAULT_SERVER
        end

        def initialize(*args)
          super
          options = args.first
          @configuration = options[:configuration]
          @configuration[:server] ||= Configuration::DEFAULT_SERVER

          @client = ::Starling.new(@configuration[:server])
        end

        def put(*args, &block)
          @client.set @configuration[:queue], args[0].to_yaml
        end

        def get(*args, &block)
          if block_given?
            loop do
              yield next_message
            end
          else
            next_message
          end
        end

        private
        def next_message
          ::SMQueue::Message(:headers => {},
            :body => YAML.load(@client.get(@configuration[:queue])))
        end
      end
    end
  end
end

Want to use it? You'll need Starling running somewhere. After that you can implement a producer in two lines of code:

producer = SMQueue(:adapter => BarkingIguana::Messaging::SMQueue::StarlingAdapter, :queue => "some.queue.name")
producer.put "Quack quack"

On the other side of the connection, here's a sample consumer:

consumer = SMQueue(:adapter => BarkingIguana::Messaging::SMQueue::StarlingAdapter, :queue => "some.queue.name")
consumer.get do |message|
  puts message.body.inspect
  # => "Quack quack"
end

One thing that's different about this adapter compared to the current SMQueue adapters is that it assumes you want to use YAML as a transport format. I'd prefer to use XML or JSON but it is at the moment just a preference, YAML is the easiest to implement, and I'm lazy.

There's also a bunch of work to do around failover - this adapter only supports one server. I still don't know enough about how Starling would handle failover so I don't want to rush into implementing that and discover I've done it wrong.

If you can help by providing patches for either other transport formats or failover please do.

Expanding shortened URLs in a Ruby String

Everyone and their dog uses some sort of URL shortening service these days. While it's handy to cram an URL into short messages like those used on Twitter it's not always considered best practice for a bunch of reasons.

Since quite a few applications these days use Twitter feeds and similar services to gather new content, it'd be great to expand those URLs and undo any damage that these services cause.

Borrowing heavily from a Ruby based Twitter client I've extracted a module which can be used to do just that. Without further ado... here it is.

require 'net/http'

module BarkingIguana
  module ExpandUrl
    def expand_urls!
      ExpandUrl.services.each do |service|
        gsub!(service[:pattern]) { |match|
          ExpandUrl.expand($2, service[:host]) || $1
        }
      end
    end

    def expand_urls
      s = dup
      s.expand_urls!
      s
    end

    def ExpandUrl.services
      [
        { :host => "tinyurl.com", :pattern => %r'(http://tinyurl\.com(/[\w/]+))' },
        { :host => "is.gd", :pattern => %r'(http://is\.gd(/[\w/]+))' },
        { :host => "bit.ly", :pattern => %r'(http://bit\.ly(/[\w/]+))' },
        { :host => "ff.im", :pattern => %r'(http://ff\.im(/[\w/]+))'},
      ]
    end

    def ExpandUrl.expand(path, host)
      result = ::Net::HTTP.new(host).head(path)
      case result
      when ::Net::HTTPRedirection
        result['Location']
      end
    end
  end
end

To use it, first include the module into String.

class String
  include BarkingIguana::ExpandUrl
end

Then simply call expand_urls or expand_urls! on the text that contains shortened URLs. The bang method changes the string in-place where the regular method returns a copy of the string and leaves the original unchanged.

s = "http://tinyurl.com/asdf"
s.expand_urls!
puts s.inspect
# => "http://support.microsoft.com/default.aspx?scid=kb;EN-US;158122"

At the moment it supports ff.im, is.gd, bit.ly and tinyurl. If you can suggest any other services I'd love to hear about them. This code - like the original implementation - is released under the MIT licence. The full code including licence and RDoc can be found at http://pastie.org/471016. Enjoy!

Memcache statistics from the command line

To help debug memcache issues it's really useful to be able to see the output of the stats command. I got bored of using telnet to talk to the memcache daemon so I whipped up this simple Ruby script to spit out the statistics without all that fuss.

#! /usr/bin/env ruby

require 'socket'

socket = TCPSocket.open('localhost', '11211')
socket.send("stats\r\n", 0)

statistics = []
loop do
  data = socket.recv(4096)
  if !data || data.length == 0
    break
  end
  statistics << data
  if statistics.join.split(/\n/)[-1] =~ /END/
    break
  end
end

puts statistics.join()

Counting tags with CouchDB and map-reduce

My previous post on CouchDB covered adding a simple view, but what if we've got a problem that can't be solved simply by mapping the existing documents to new documents? What if we want to get a list of each tag used in articles along with a count of how many articles use that tag? Sure, we could emit doc.tags then munge the resulting arrays in the client language, but wouldn't it be great if CouchDB would do that for us?

Well, yes, it would be great, and CouchDB can do it for us.

As a reminder, here's an example of the article documents that I'm using.

{
  "_id": "monkeys-are-awesome",
  "_rev": "1534115156",
  "type": "article",
  "title": "Monkeys are awesome",
  "posted_at": "2008-09-14T20:45:14Z",
  "tags": [
    "monkeys",
    "awesome"
  ],
  "status": "Live",
  "author_id": "craig@barkingiguana.com",
  "updated_at": "2008-09-14T21:23:59Z",
  "body": "The article body would go here..."
}

It's fairly easily add a view that, for each document, will return a count of how many times that document has been tagged by each tag.

function(doc) {
  if(doc.type == 'article') {
    for(i in doc.tags) {
      emit(doc.tags[i], 1);
    }
  }
}

For the example article document this would return ("awesome", 1) and ("monkeys", 1), but if there were several documents tagged "monkeys" then this would return ("monkeys", 1) several times.

What we want to do now is to reduce the result set to a list of unique tags and the number of times those tags were found in the results.

The reduce takes the form of a method. It's called once for each unique instance of a key that appears in the map output and is passed the key and an array of all values that the map emits with that key.

Since our keys are tags and our values are numbers we simply need to add all the numbers for each key.

function(tag, counts) {
  var sum = 0;
  for(var i=0; i < counts.length; i++) {
     sum += counts[i];
  }
  return sum;
}

This can be installed in the same way as a map function, just with the key "reduce".

{
  "tags": {
    "map": "function(doc) { if(doc.type == 'article') { for(var i in doc.tags) { emit(doc.tags[i], 1); }}}",
    "reduce": "function(tag, counts) { var sum = 0; for(var i = 0; i < counts.length; i++) { sum += counts[i]; }; return sum; }"
  }
  // other views omitted for brevity
}

Looking at this view in Futon will get you a nicely formatted list of tags and a count of the number of documents that have the tag. To use the view directly you must ask CouchDB to group the results by key.

// GET http://localhost:5984/blog/_view/articles/tags?group=true&group_level=1

{"rows":[
  {"key":"awesome","value":1},
  {"key":"agile","value":2},
  {"key":"ajax","value":2},
  {"key":"apache","value":2},
  {"key":"api","value":1},
  {"key":"caching","value":1},
  {"key":"coding","value":7},
  {"key":"conference","value":1},
  // and so on ...
]}

Filtering and ordering CouchDB view results

Being able to map documents to (key, value) pairs is really useful, but the views installed in my previous post return all pairs that the view calculates in no specific order. What if I want only the titles of articles posted in December 2007?

In the last article I mentioned in passing that it was possible to emit keys as part of the map method of a view. Keys are used to order and filter a result set. Details about how keys are sorted against each other can be found in the CouchDB view collation specification. To order and filter documents by date posted I just need to emit doc.posted_at as the key when I'm writing my map method.

// Get all article titles ordered by posted date.
function(doc) {
  if(doc.type == 'article') {
    emit([doc.posted_at], doc.title);
  }
}

It's worth noting that I've chosen always to have my keys be arrays. This is a personal preference - it was easier to make my branch of ActiveCouch support multiple keys if I assumed this.

A typical result set from running this map might look like the following.


// GET /blog/_articles/titles_by_posted_at
{
"total_rows":75,
"offset":0,
"rows":[
  {"id":"showing-multiple-message-types-with-the-flash","key":["2007-12-15T20:14:02Z"],"value":"Showing multiple message types with the flash"},
  {"id":"class-instance-and-singleton-methods","key":["2007-12-20T14:50:41Z"],"value":"Class, Instance and Singleton methods"},
  // ... and so on ...
}

Now that the articles are keyed by date note that they're ordered by the data - the lower the date value the earlier they are in the results.

The key can also be used to pick out specific articles. Maybe I want just the article that was published at 2007-12-20T14:50:41Z, I just ask for that key from the results.

// GET /blog/_articles/titles_by_posted_at?key=["2007-12-20T14:50:41Z"]

{"total_rows":75,"offset":0,"rows":[
{"id":"class-instance-and-singleton-methods","key":["2007-12-20T20:50:41Z"],"value":"Class, Instance and Singleton methods"}
]}

If I wanted to pull out a range of results I can specify a startkey and an endkey and all results that have a key that falls between the two will be returned. I can take advantage of the fact that the keys are strings too, and specify times that might otherwise not make sense such as 24:00 to make sure that I get all articles that I'm interested in.

// GET /blog/_view/articles/titles_by_created_at?startkey=[%222007-12-01T00:00:00Z%22]&endkey=[%222007-12-31T24:00:00Z%22]

{"total_rows":75,"offset":0,"rows":[
{"id":"showing-multiple-message-types-with-the-flash","key":["2007-12-15T20:14:02Z"],"value":"Showing multiple message types with the flash"},
{"id":"class-instance-and-singleton-methods","key":["2007-12-20T14:50:41Z"],"value":"Class, Instance and Singleton methods"}
]}

The key, startkey and endkey are three of a whole bunch of parameters available as part of CouchDB's view API. More information can be found at http://wiki.apache.org/couchdb/HTTP_view_API.

Adding a simple view to CouchDB

CouchDB views are sort of like scripts that run inside CouchDB which manipulate and massage the documents inside the database into a (key, value) pair, then return those pairs which contain keys that match a query you run against the view. When I started playing with CouchDB I couldn't work out how to add views, thinking that there was something I was missing.

To show how to create a view and add it to the database let's take an example problem. Say you have several documents that describe articles in your database.

{
   "_id": "monkeys-are-awesome",
   "_rev": "1534115156",
   "type": "article",
   "title": "Monkeys are awesome",
   "posted_at": "2008-09-14T20:45:14Z",
   "tags": [
       "monkeys",
       "awesome"
   ],
   "status": "Live",
   "author_id": "craig@barkingiguana.com",
   "updated_at": "2008-09-14T21:23:59Z",
   "body": "The article body would go here..."
}

You might create a view that would give you the id and title of all documents in the database. To do this you would ask CouchDB to map each existing document to a new document containing the document id and the document title. This takes the form of a method which accepts each document as an argument and returns the document or result that you'd like to get back from the view.

function(doc) {
  emit(null, { 'id': doc._id, 'title': doc.title });
}

For just now ignore that the first argument to emit is null. It's for emitting the key that will be used to sort and filter results. I'll cover it in my next post.

While writing a view it can be useful to filter documents so that you only get the desired types emitted - in this case I only want the id and title of article documents. Documents that represent, for example, comments, may not have a title attribute.

function(doc) {
  if(doc.type == 'article') {
    emit(null, { 'id': doc._id, 'title': doc.title });
  }
}

Adding this view to the database it pretty simple: just add a design document to the database. Design documents are just the same as any another document you'd add to CouchDB except they must have an identifier that starts _design/ for example _design/articles. To insert the document you can use the built-in admin client, Futon, which is available at http://localhost:5984/_utils/.

The full JSON document for a view which gives back the id and title for all documents in the database is shown below.

{
  "_id": "_design/articles",
  "_rev": "42351258",
  "language": "javascript",
  "views": {
    "titles": {
      "map": "function(doc) { emit(null, { 'id': doc._id, 'title': doc.title }); }"
    }
  }
}

Fire up Futon, access your database, add a new document and paste the view in. Once installed you can easily see the results of a view by clicking the drop-down that Futon shows when viewing a database. It's in the top right and it's labelled "select view". To get the raw JSON documents returned by your view you'll need to access your database directly. If your database was called "blog" then you could access the above view at http://localhost:5984/blog/_view/articles/titles.

There can be many views in one design documents, each with a different name, and each returning different kinds of results. Here's one that's got that a few views that use the soon-to-be discussed "key" emitted.

{
  "_id": "_design/articles",
  "_rev": "28651884",
  "language": "javascript",
  "views": {
    "all": {
      "map": "function(doc) { if(doc.type == 'article') { emit(null, doc); }  }"
    },
    "by_author_id": {
      "map": "function(doc) { if(doc.type == 'article') { emit([doc.author_id], doc); }  }"
    },
    "by_status": {
      "map": "function(doc) { if(doc.type == 'article') { emit([doc.status], doc); }  }"
    },
    "titles": {
      "map": "function(doc) { if(doc.type == 'article') { emit(null, { 'id': doc._id, 'title': doc.title }); } }"
    }
  }
}

Managing Gem dependencies with Rails >= 2.0.3

This is how I manage gem dependencies for Rails applications that use Rails >= 2.0.3.

Specify the dependencies in config.rb.

Rails::Initializer.run do |config|
  # ...
  config.gem 'doodle'
  config.gem 'aws-s3', :lib => 'aws/s3'
  config.gem 'smqueue', :version => '0.1.0'
  # ...
end

Since I don't want to make my deployment depend on all the gem sources being available I tend to pull the gems into the source tree and check them in.

sudo rake gems:install
rake gems:unpack
svn add vendor/gems/*

When it's time to deploy the application remember to build the gems that have native extensions.

rake gems:build

If you've got some sort of build system in place that produces application packages then this should be done as part of building that package. If you're using Capistrano then it should be done in an after deploy:update_code callback.

When should a merge be squashed?

I'm still somewhat new to Git so now and again I come up with a question that's so obvious to other developers that it doesn't seem to be answered anywhere. One such question is "when should a merge be squashed?"

Squashing a merge means taking all the commits that would normally be replayed individually on your target branch and replaying them as one large commit.

Well, as far as I can tell, here's the answer: squashing a merge is appropriate when all the commits in the merge deal with one topic.

As an example, consider having a branch that deals with the performance of one particular method. Each time you increase the performance you commit your changes. After a few days of this you have several commits in your branch and a lovely fast implementation that you want to merge back to the master branch. The merge from your branch to master should be a squashed commit and your commit message should explain what you did to speed up the implementation.

git merge --squash speed-up-the-method

An unsquashed commit could be more appropriate if you're merging from a development branch since in this case the branch should be composed of a nicely formatted series of commits based on topic relevant to the development branch.

git merge dev/v1.2.3

When doing an unsquashed commit your repository will use the original commit messages.

Symbol#to_proc is slow... is it slow enough to matter?

It's common knowledge that using the to_proc hack is slower than not. Just how much slower is it? I decided to put together a few benchmarks to find out.

Environment

These tests were run on Ruby 1.8.6-pl111 and Rails 2.1.

Benchmarking

Say there's a database of 1,000 items that for some reason you want to iterate over. Let's forget that if you're showing 1,000 items you probably have usability issues and just roll with it.

1_000.times { |n| Bar.create :name => "bar-#{n}" }
bars = Bar.find(:all)

Here's how much slower it is over a dataset of 1,000 ActiveRecord instances.

Benchmark.measure { bars.map(&:name) }.real
#=> 0.00645709037780762

Benchmark.measure { bars.map { |b| b.name } }.real
#=> 0.00141692161560059

Now that's a horrific increase: it takes more than 350% longer to run the to_proc hack than the plain block... but let's be realistic here, over 1,000 records it's taken 0.0065 seconds. Big woop. Who cares?

How about over 1,000,000 rows? We already have 1,000 rows, let's top that up.

(1_000_000 - 1_000).times { Bar.create :name => Time.now.to_f.to_s }
bars = Bar.find(:all)

That makes it 1,000,000 rows in the table. By this stage your database is probably thinking you hate it. I'm pretty confident that presenting 1,000,000 rows to the person using your application is a bit of an edge case, but hey, here's how long it takes.

Benchmark.measure { bars.map(&:name) }.real
#=> 6.25304508209229

Benchmark.measure { bars.map { |b| b.name } }.real
#=> 1.38965106010437

Almost 5 seconds extra over a million rows. Okay so 5 seconds is a pretty big hit, but how long will your application be running before you hit a million rows in one of your tables and you need to iterate over all million rows?

Don't optimise your code prematurely. By the time to_proc becomes an issue you'll already have hit many, many other problems.

Benchmark.measure { Bar.find(:all) }.real
#=> 406.738657951355

Worry about those first.

Handling error feedback from Ajax requests to Rails applications

Ajax is frequently used to provide a richer user experience. Why then are important error messages rarely handled properly in Ajax enabled applications? Handling errors gracefully and in a way that helps the visitor to solve them adds a really high quality feel to your application. We've got all the necessary machinery, all it takes is a little care and attention.

class FoosController < ApplicationController
  def update
    @foo = Foo.find(params[:id])
    respond_to do |format|
      if @foo.save
        format.html do
          flash[:info] = "Your foo has been created."
          redirect_to @foo
        end
        format.js { head :ok }
      else
        format.html do
          flash.now[:warning] = "I could not update the foo."
          render :action => :edit
        end
        format.json do
          head :unprocessable_entity, :json => @foo.errors.to_json
        end
      end
    end
  end
end

Using the above code we get a lovely fallback HTML based behaviour and when we work with Ajax we get to use JSON behaviours. When JSON is requested and something goes wrong we get back an array of arrays that takes the following form.

[
  [ "attribute1", "error1", "error2" ],
  [ "attribute2", "error3"]
]

Just think of the awesome things you could do with such rich feedback...

new Ajax.Request('/foo.json', {
  method: 'PUT',
  parameters: {
    authenticity_token: window._token,
    "foo[subject]": $F('foo_subject'),
    "foo[body]"   : $F('foo_body')
  },
  onSuccess: function(transport) {
    // This is Web 2.0: celebrate with a yellow highlight.
  },
  onFailure: function(transport) {
    var errors = transport.responseJSON;
    errors.each(function(error) {
      var attribute = error.shift();
      var messages = error.join(", ");
      var errorMessage = attribute + " " + messages;
      var inputNode = $("foo_" + attribute);
      if(inputNode) {
        // Show that something is wrong with this field.
        inputNode.addClassName("error");
        // Do something better than an alert box. Alert boxes suck.
        alert(errorMessage);
      }
    });
  }
});

Ajax and the Rails request authenticity token

Rails 1.2.6 introduced CSRF protection in the form of an authenticity token which is a reasonably long string used to make sure that any PUT / POST / DELETE request you've made to an application was really generated by you (or at least your browser) doing something in the application and that you weren't tricked into submitting it by some nefarious third party.

Rails automatically adds this token to any forms generated by it's helpers, but when building rich Ajax applications it can be useful to be able to generate the Javascript by hand.

Fire this snippet into your layout just above including all the other Javascript files to get access to the authenticity token in Javascript and let you submit requests using Ajax.

<%= javascript_tag "window._token = '#{form_authenticity_token}';" %>

Now you can build Ajax requests that are allowed to do stuff to the application.

new Ajax.Request('/foo.json', {
  method: 'PUT',
  parameters: {
    authenticity_token: window._token,
    text: $F('foo_text')
  }
  /* callbacks omitted for brevity */
})

Get the current Git branch in your command prompt

It seems that everyone and their dog has their own way to represent the current Git branch in the command prompt. Here's mine. Stick it in your ~/.profile.

export PS1='\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]$(git branch &>/dev/null; if [ $? -eq 0 ]; then echo "\[\033[01;33m\]($(git branch | grep ^*|sed s/\*\ //))\[\033[00m\]"; fi)$ '
craig@shiny ~/sandbox/addressbook(master)$

Now with 50% cleaner code

Not long after I posted this snippet I found a post about enabling git auto-completion. If you use the auto-complete file that's bundled with Git you can use the following code to get the same prompt (and get some nifty tab-based goodies too).

export PS1='\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]$(__git_ps1 "\[\033[01;33m\](%s)\[\033[00m\]")$ '

Content_for is the new GOTO

I don't like content_for. Your view code jumps around up and down files and makes it hard to work out what's going on. It smells a lot like GOTO. When was the last time you saw someone recommend you use a GOTO?

content_for :javascript and content_for :css

Use of content_for can be easily avoided, at least for including CSS and Javascript files. Include the controller name and action name in the body tag in your layout and properly qualify your CSS declarations.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title><%= page_title %></title>
  <meta http-equiv="Content-Language" content="English" />
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <link rel="stylesheet" type="text/css" href="/stylesheets/simple.css" media="screen" />
</head>
<body id="<%= "#{controller.controller_name.tableize.singularize}_#{controller.action_name}" %> class="<%= "#{controller.controller_name.tableize.singularize} #{controller.action_name}" %>">
  <%= yield %>
</body>
</html>

Say you were looking at the Posts views in your app, you can now style these using something like this.

.post.index .article .title { 
  font-size: 1.25em;
}

.post.show .article .title { 
  font-size: 0.9em;
}

Or, in case you need to support browsers that don't let you specify two classes as a selector for a single element, you can write it like this.

#post_index .article .title { 
  font-size: 1.25em;
}

#post_show .article .title { 
  font-size: 0.9em;
}

Since all your Javascript is unobtrusive anyway (right?), it should be pretty easy to qualify the selectors used there with the same CSS selectors shown above.

As an added bonus, by specifying your Javascript / CSS like the above you can package it all in one Javascript or CSS file on deployment to your production environment and save yourself a bunch of HTTP requests.

Make sure you're @importing files that exist

A few people near me have heard the start of my rumblings about optimising the number of HTTP requests required for each page. There are a variety of reasons that you might want to do this, but that discussion is for another post. For now simply assume that I don't like unnecessary HTTP requests. Extrapolating from that you would reasonably assume that I really don't like wasted HTTP requests such as might happen when the url in a CSS @import directive 404's. If you assumed that, you'd be right.

I got fed up of tracking down the source of these errors in a few applications that I maintain so I fired up a TextMate session and scraped together this nasty little snippet of Ruby to do my dirty work for me.

#! /usr/bin/env ruby

css_root = File.expand_path(`pwd`.strip)
css_files = Dir[File.join(css_root, "**", "*.css")]

missing_imports = Hash.new([])
css_files.each_with_index do |css_file, index|
  imports = File.read(css_file).split(/\n|\r/).grep(/\@import url\((.*)\)/)
  imports.each do |import|
    desired_path = import.scan(/url\((["'\ ])?(.*)\1\)/).to_a.first.to_a.last
    desired_root = desired_path[0,1] == "/" ? css_root : File.dirname(css_file)
    filesystem_path = File.expand_path(File.join(desired_root, desired_path))
    if !File.exists?(filesystem_path)
      missing_imports[css_file] += [{ :path => filesystem_path, :directive => import }]
    end
  end
end

if missing_imports.any?
  puts "Missing files declared as imports in CSS:\n\n"

  missing_imports.keys.each do |origin|
    puts "Origin:               #{origin}"
    missing_imports[origin].each do |import|
      puts "Missing @import file: #{import[:path]}"
      puts "Directive:            #{import[:directive]}"
    end
    puts ""
  end
else
  puts "No imported files are missing. Well done."
end

Run it in the directory which serves your document root - for Rails applications this would be RAILS_ROOT/public/ - and it'll either spit out a list of missing files you've tried to @import or tell you that you've done well.

Missing files declared as imports in CSS:

Origin:               /Users/craig/projects/1.8/public/stylesheets/.../find_by_service.css
Missing @import file: /Users/craig/projects/1.8/public/stylesheets/.../a_to_z.css
Directive:            @import url('.../a_to_z.css');

Now, just to be clear, I don't like @import directives. I'd prefer they were completely removed from the CSS. They are popular with a lot of people though so I'll compromise for the moment: if you must use them, please make sure they're going to work.

Talking to yourself is bad mmkay?

A lot of languages encourage talking to yourself. Lots of OO PHP code is sprinkled with code that looks like $this->foo_method();. In some languages it's necessary. Ruby isn't one of them.

class Foo
  def bar
    # Why are you talking to yourself?!
    @thingy = self.foo
  end

  def foo
    "QUUX!"
  end
end

The code above could be written without self at all.

class Foo
  def bar
    @thingy = foo
  end

  def foo
    "QUUX!"
  end
end

While this is a (very) trivial example, it makes a huge difference on larger code-bases. Give it a try: if you don't talk to yourself your code will look less crazy.

Only one caveat: when you're doing assignment you'll need to talk to yourself unless you're doing a local assignment.

class Foo
  attr_accessor :thingy

  def bar
    # This will assign to a local variable.
    thingy = foo
  end

  def foo
    "QUUX!"
  end
end
class Foo
  attr_accessor :thingy

  def bar
    # This will call Foo#thingy=
    self.thingy = foo
  end

  def foo
    "QUUX!"
  end
end

LDAP authentication in an Apache fronted Rails app

If you manage anything but the simplest of setups you've probably got an LDAP server setup providing directory services to your network. If you don't you should probably stop reading now ;)

Authenticate using LDAP

The first step to getting your Rails application authenticating using LDAP is to get Apache to authenticate all requests before they reach the application. This stuff is tricky and Apache already has a rather lovely module, mod_authnz_ldap, that does all the heavy lifting for us.

<VirtualHost 193.219.108.xxx:443>
  # I've used port 443 above because I'm dealing with passwords.
  # [...snip...]
  <Directory /var/www/foo.example.com/current/public>
    AuthType Basic
    AuthName "Foo Application Control Panel"
    AuthBasicAuthoritative off
    AuthBasicProvider ldap
    AuthLDAPUrl ldap://ldap.example.com/ou=people,dc=example,dc=com?userid?one
    Require valid-user
  </Directory>
  # [...snip...]
  # Your normal Rails HTTP configuration goes here
</VirtualHost>

Look up the user in Rails

Okay, so any request that hits your application is now authenticated against your LDAP directory. Next, tell Rails to look for the user. For authentication I wrote a rather funky (if I do say so myself) mixin, Xeriom::Acts::ProtectedSystem.

module Xeriom # :nodoc:
  module Acts # :nodoc:
    module ProtectedSystem # :nodoc:
      def self.included(base)
        base.send(:extend, ClassMethods)
      end

      module ClassMethods
        def acts_as_protected_system
          include InstanceMethods
          send(:before_filter, :ensure_user_is_logged_in)
          send(:helper_method, :current_user)
          send(:helper_method, :logged_in?)
        end
      end

      module InstanceMethods
        def ensure_user_is_logged_in
          if !logged_in?
            authenticate_user
          end
        end

        def logged_in?
          !current_user.blank?
        end

        def current_user
          @current_user ||= User.find_by_id(session[:user_id])
        end

        def current_user=(user)
          @current_user = user
          session[:user_id] = user.blank? ? nil : user.id
        end

        def authenticate_user
          authenticate_or_request_with_http_basic("Protected Area") do |username, password|
            # Lock your application servers down to listen to only
            # the web tier or this will kick your ass.
            send(:current_user=, User.find_by_username(username))
          end
        end
      end
    end
  end
end

ActionController::Base.send(:include, Xeriom::Acts::ProtectedSystem)

Like the code licence section in the sidebar says: this code is totally public domain, just don't sue me. To use it just drop the code in your lib/ directory and then call acts_as_protected_system in your ApplicationController.

class ApplicationController < ActionController::Base
  helper :all # include all helpers, all the time
  protect_from_forgery # because CSRF sucks!
  acts_as_protected_system # lock the door
end

For bonus points...

If you found this article useful, give me some love over at Working With Rails.

Using signals to debug long-running processes

Sometimes a long-running process will start to perform it's tasks much slower than it should, or in a strange order. It'd be lovely to know what the process is doing but strace produces a deluge of information that is several levels below what you want to know. What can you do?

Well, we could ask the process to turn on debugging output while it's still running. How does that sound?

trap("USR1") do
  $DEBUG = !$DEBUG
  @logger.level = $DEBUG ? Logger::DEBUG : Logger::INFO
  @logger.info "USR1 received. Turning #{$DEBUG ? 'on' : 'off'} debugging."
end

Now whenever you need more debugging information simple send a USR1 signal to your process.

kill -USR1 [pid]

Verify database connections in long-running idle Rails processes

I've interfaced one of my xmpp4r bots with the Xeriom Networks control panel. I had intended to write a post about it to show how easy it is, but I've been beaten to it. I can, however, offer one piece of advice that will stop the bot dying after a few hours of idling: periodically verify your database connections.

RAILS_DEFAULT_LOGGER.debug "Launching database connection verifier"
Thread.new do
  loop do
    sleep 1800 # Half an hour
    RAILS_DEFAULT_LOGGER.debug "Verifying database connections"
    ActiveRecord::Base.verify_active_connections!
  end
end

Adding the above code to a script will stop database connections getting dropped (or, at least, will reconnect them if it happens).

To see it in action, add support@xeriom.net to your XMPP roster and have a chat. It's not hugely intelligent, but it does support a few useful commands.

Update: the support bot is no longer running. It was fun, but not hugely useful in this context.

Love me!

If you've found this article useful I'd appreciate beer and recommendations at Working With Rails.

Getting started with CouchDB: A simple address book application

I've recently installed CouchDB but, still being pretty new to this whole document store thing, don't really know what they can do or how to make CouchDB do it.

The best way to learn, of course, is to do. I've decided that I'll implement a simple address-book implementation.

Investigation and technology choice

Since CouchDB talks JSON I figure that I'll write the address book in Javascript and HTML, and because CouchDB includes a web server I'll serve the application from the same place I store the data. I'll call the file that contains that addressbook application addressbook.html.

Taking a peek at the CouchDB configuration in /usr/local/etc/couchdb/couch.ini I see that the document root for the web server can be found at /usr/local/share/couchdb/www - that's where the addressbook.html file will go.

I'll need a database to store people's contact details in. There's a pretty nice interface to do this at /_utils/ which is accessible using a web browser by pointing it at the CouchDB server's IP address and port.

CouchDB comes with a Javascript wrapper which can be found at /_utils/script/couch.js but it only talks to a local server and I'm accessing the page across the internet so I'll steal some code from it and change it to work for my setup.

Implementation

First off, create the database. Jump into the interface at /_utils/ and create a database called "addressbook". That's where we'll store our data.

The user interface is going to be a webpage using Javascript which makes things pretty simple. I'll whip up a really simple page to start with.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <!-- The javascript will live in addressbook.js -->
  <script src="http://aaa.bbb.ccc.ddd:5984/_utils/addressbook.js"></script>
  <title>Address Book</title>
</head>
<body>
  <h1>Address Book</h1>
  <div id="addressbook">
    <p id="loading">Loading... please wait...</p>
  </div>
</body>
</html>

Since I've been spoiled by ActiveRecord I want to be able to say something like var people = Person.find("all"); in my code and have it return all Person records. I also want to be able to say Person.find("123456-1234-1234-123456"); to find an individual person.


Person = {
  // Push the implementation details of the database into a 
  // different object to keep Person clean.
  //
  database: AddressBook,
  find: function(id) {
    if(id == "all") {
      return this.database.allCards();
    } else {
      return this.database.openCard(id);
    }
  }
}

I've chosen to implement an AddressBook object that will abstract the details of database connection from the Person object. It will provide two methods, allCards and openCard(id). These methods talk to the CouchDB server and handle any and all data marshalling or other tricky bits and pieces.

AddressBook = {
  // Change this to point to your own CouchDB instance.
  uri: "http://craig-01.vm.xeriom.net:5984/addressbook/",

  _request: function(method, uri) {
    var req = new XMLHttpRequest();
    req.open(method, uri, false);
    req.send();
    return req;
  },

  // Fetch all address book cards.
  allCards: function() {
    var req = this._request("GET", this.uri + "_all_docs");
    var result = JSON.parse(req.responseText);
    if (req.status != 200)
      throw result;
    var allDocs = [];
    for(var offset in result.rows) {
      var id = result.rows[offset]["id"];
      var doc = this.openCard(id);
      allDocs[allDocs.length] = doc;
    }
    return allDocs;
  },

  // Fetch an individual address book card.
  openCard: function(id) {    
    var req = this._request("GET", this.uri + id);
    if (req.status == 404)
      return null;
    var result = JSON.parse(req.responseText);
    if (req.status != 200)
      throw result;
    return result;
  }
}

I push responsibility for parsing JSON off to another library. Luckily, Yahoo provide a rather nice JSON library that does just what I'm looking for - I don't have to implement it, but I do need to pull it into the webpage, and make it appear in the global namespace.


<!-- Add this to the head of addressbook.html -->
<script src="http://yui.yahooapis.com/2.5.2/build/yahoo/yahoo-min.js"></script>
<script src="http://yui.yahooapis.com/2.5.2/build/json/json-min.js"></script>

// Make YUI JSON available in the global namespace.
// Add this to addressbook.js
JSON = YAHOO.lang.JSON;

The last piece of Javascript I need to show the address book is something to load all people from the address book and add them to the page. This uses window.onload hook which is bad, but for this little application is a quick and easy to kick off some code.

// This is horrible, I know, but it's just a simple example.
window.onload = function() {
  var addressbook = document.getElementById("addressbook");
  var personList = document.createElement("ul");
  for(var offset in people) {
    var person = people[offset];
    var personNode = document.createElement("li");
    var name = document.createTextNode(person.name);
    personNode.appendChild(name);
    personList.appendChild(personNode);
  }
  addressbook.removeChild(document.getElementById("loading"));
  addressbook.appendChild(personList);
}

That's it; the application is ready to go. Upload the addressbook.html and addressbook.js file to the document root of the CouchDB server, fire up your browser and navigate to http://aaa.bbb.ccc.ddd:5984/_utils/addressbook.html where aaa.bbb.ccc.ddd is the IP address of your CouchDB instance.

A blank page that says "Address Book" should greet you. Not very impressive, right? What went wrong? Actually, nothing went wrong. There's just no data in the database.

The interface that I pointed out before for browsing and creating databases can also be used to add documents to the database. Jump into it again, navigate to the addressbook database and add a document. When it asks you for an id, just leave the field blank: it'll create one automatically. Add a field to the document called name and click the little green checkbox beside the textbox, then double click on the value of the new field and set it to your own name in quotes eg "Craig Webster". Click the green arrow beside the textbox then click "save document", jump back to the address book and hit refresh. The new record should now show up.

Moving forward

I've shown how to retrieve data from CouchDB using Javascript, but currently the data still has to be input using the CouchDB interface. Watch this space for an upcoming article on manipulating the database using Javascript so we can add cards to the addressbook.

Did this article help?

If this article helped you, I appreciate beer if you meet me, or recommendations at Working With Rails.

XMPP4R-Simple makes XMPP in Ruby uhh... simple...

I thought it might be cool to have a control interface that you could talk to using IM, something like the IM client for Twitter.

Initially I was looking at XMPP4R but a little reading pointed out that there's a gem called XMPP4R-Simple. Well, simple is always good so one gem install and 45 minutes later I had a Ruby script that could log in to an XMPP server, listen to (and log) what people said, and respond with a simple message.

#!/usr/bin/env ruby

require 'rubygems'
require 'xmpp4r-simple'

logfile = File.join('..', 'log', "#{File.basename(__FILE__)}.log")
logger = Hodel3000CompliantLogger.new(logfile)

jabber = Jabber::Simple.new "username@domain.com", "password"
sleep 1
jabber.status(:away, "No one here but us mice.")
sleep 1

jabber.deliver("craig@xeriom.net", "I woke up at #{Time.now}.")

loop do  
  begin
    jabber.received_messages do |msg|
      jid = msg.from.strip.to_s
      logger.info "%s said: %s" % [ jid, msg.body ]
      jabber.add(jid) if !jabber.subscribed_to?(jid)
      jabber.deliver(jid, "Nom nom nom.")
    end

    jabber.presence_updates do |update|
      jid, status, message = *update
      logger.info "#{jid} is #{status} (#{message})"
    end

    jabber.new_subscriptions do |friend, presence|
      logger.info "#{friend.jid} #{presence.type}"
      jabber.add(friend.jid) if !jabber.subscribed_to?(friend.jid)
    end
  rescue Exception => e
    logger.error e.to_s
  end
  sleep 1
end

Our own little pet XMPP client. How cute is that?

Quit yo jibba jabba, sucka!

If you've found this article useful I'd appreciate recommendations at Working With Rails.

The end of the world is nigh

According to Ruby, the world ends (or, at least, is reconfigured) on Tuesday the 19th of January 2038 at 7 seconds past 3.14am.

>> Time.utc(2038, 1, 19, 3, 14, 7, 999999)
=> Tue Jan 19 03:14:07 UTC 2038
>> Time.utc(2038, 1, 19, 3, 14, 7, 999999).succ
=> Fri Dec 13 20:45:52 UTC 1901

This is an artefact of representing time as an integer counting from the epoch, but given that a Fixnum will automatically roll over into a Bignum when it reaches 2**30, it's somewhat surprising that a similar transformation isn't performed internally in Time to allow us to represent dates and times beyond 2038-01-19.

Showing multiple message types with the flash

Traditionally the Rails flash is used to store only one message, usually in flash[:message] but I like to be able to differentiate between warnings and information in my view rather than displaying them both in the same place in the same style.

The flash is a HashWithIndifferentAccess so we can use any key we want to store messages and pull them back out later, in the view.

In your controller you simply use whichever key is most appropriate.

if @widget.save
  flash[:info] = "Your widget has been saved."
  flash[:notice] = "There are now #{Widget.count} widgets."
  redirect_to @widget and return
else
  flash.now[:warning] = "I couldn't save your widget."
  render :action => "edit"
end

In the view you can now iterate over the flash and pick out the key and the message.

<%= flash.sort.collect do |level, message|
  content_tag(:p, message, :class => "flash #{level}", :id => "flash_#{level}")
end.join %>

Say the @widget got saved earlier, you'd end up with some easily understood and styled markup.

<p class="flash info" id="flash_info">Your widget has been saved.</p>
<p class="flash notice" id="flash_notice">There are now 29 widgets.</p>

Of course, in the interest of readability the flash loop in the view should be extracted to a helper, but that's left as an exercise for the reader.

About the boy

A picture of Craig in grayscale

Craig Webster is a software engineer living in London. He usually works with Ruby although sometimes he sneaks in some Erlang or JavaScript. He's into rock climbing, snowboarding, skating, photography and fencing. Yes, this does mean he has a sword.

Near here you'll find Craig's homepage, contact details, PGP key and keysigning policy, and talks.

Licence

The entire content of this blog is public domain. Use it however you fancy. You don't even need to attribute it to me, although it would be nice if you did. Just don't sue me and we'll all be happy.

I Work With Rails

Recommend Me

My Travels

I go places. Do you go places too? Let's meet up!.