Lately, with my friend and colleague Joseph, we made some experiments with the Sinatra Ruby Framework.

As part of the experiment we’ve chosen to stick with our DB of choice PostgreSQL and our preferred template engine HAML, but we decided to give the SequelORM a try as well as using Ruby 1.9.1. We also wanted to store our datas as UTF-8 (this part is the most painful of all).

Our first goal was to have a simple application tying everything together and testable with RSpec and Cucumber.

Using Sinatra and HAML is a snap, as it’s a core feature of Sinatra, just be sure to use HAML version >= 2.2.0 as it includes some work to support new Ruby 1.9 String Encoding.

Then comes Sequel, using it is as simple as requiring it and feeding it with database connection information, just be sure to set the :encoding => 'UTF-8' (cf : Sequel::Database.connect method).
Sequel is great in that it has adapters for most commons connectors, first we tried DataObjects’s do_postgres as it should support asynchronous query (and it does !), but we had to fall back to the PG one and even to a patched version.

Let me explain the problem here, and be warned it’s not limited to Sequel, but to any ORM using currently available db connectors, when using a charset different from ASCII-8BIT under Ruby 1.9.
What happens is that ORMs do not force any encoding on String returned by the database connectors even when you specified an encoding (commonly used to set the connection’s “client_encoding”). Current ruby connectors (under Ruby 1.9) do not use the database/client’s connection encoding as a “hint” to determine and set the encoding of returned values.
This is not a problem on Ruby 1.8, but on Ruby 1.9 you get some weird results, the string returned from db have a default encoding “ASCII-8BIT” (in fact default for BINARY), as ORMs do not force encodings this result in a String with the bad Encoding.
Try to display it on a page and you’re welcomed with friendly “incompatible character encodings: ASCII-8BIT and UTF-8.” messages or try to use Webrat with RSpec matchers and you get “incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string)”.

So here are the libraries versions to use to have a working Sinatra, Sequel with Postgres, HAML, RSpec, Cucumber stack :

Sinatra >= 0.9.4

Rack-Test >= 0.4.1

Webrat >= 0.5.0

kamk-pg >= 0.8.0.3 (http://github.com/kamk/pg/tree/master)

Sequel >= 3.0.0

RSpec >= 1.2.8

Cucumber >= 0.3.94

Then you need to monkey-patch Rack (this is highly untested, it worked for my current app but it should not be used in production environment) :

Due to the increasing time/resources needed to generate the indices for my rubygems mirror, I decided to stop generating the ones for old RubyGems versions (<= 1.2.0) and switch to the —update option.

This greatly help with the load generated on the server by the mirroring/indexing process. From now on I will only generate the legacy indices (for RubyGems <= 1.2.0) twice a day : 12AM UTC+2/12PM UTC+2.

The interesting method is capture_haml, which does the same as Rails builtin capture but for HAML. haml_tag/puts methods write output directly to the buffer and does not return the generated content as a String, thus we cannot just test on the method output.

I encountered, for some time now, problems when connecting over ssh from my mac to a linux machine.
These problems were related to backspace/delete key in both nano and zsh the solutions I found today are :

Following my last post, here’s another handy new thing to do in Leopard. I never used this in Tiger (MacOS X.4) because it was not practical (besides being possible), but I swear it was usable by the time.
Auto-mounting remote shared server (Samba, NFS, AFS) wherever I want, without being stuck with a dead Finder.app whenever I lost wifi network, I change room or my mac goes to sleep (yep I used to have some problems with this).
So now how to do this ? NetInfo is gone so where can I define my automount points, remember when I said NetInfo is dead for the best ?

-fstype=smbfs : specify the kind of filesystem to use, I only cover samba here.

://username:passwordremote_server_name_or_ip/shared_folder_name@ : this is the informations to connect to the remote server. Change username and password with yours, specify remote_server_name_or_ip to reflect the way you access the machine and set shared_folder_name to the name of the remote folder.

Notice just like /etc/hosts that Leopard seems to only detect a change if a line is added/removed, so anytime you make a change that does not change the line number in the file add a comment (#) at the beginning or end to force a reload.

Back in Tiger days, I used to love having aliases pointing to localhost or other servers saving me some typing and allowing me to use Apache vhosts locally. To achieve this without restarting the whole system, I used NetInfo to add a new Machine entry, this works great, no restart needed only NetInfo reload.

With Leopard, NetInfo is gone (for the best) and it has been replaced by a folder hierarchy full of flat .plist files. No more NetInfo Manager, but a new dscl command and a bunch of related one : dscacheutil (lookupd replacement), dseditgroup, dsmemberutil, etc.

For today, we’ll use dscl and dscacheutil, let’s create a new Host entry to map myvhost.loc to 127.0.0.1 (I like adding .loc to distinguish my added hosts, but you’re free to use anything else) :

Then to be sure it’s looked up correctly by software (in fact it’s only needed if you tried to access the myvhost.loc before adding it) :

sudo dscacheutil -flushcache

A little handy feature of the new dscacheutil when we’re at it :

sudo dscacheutil -cachedump -entries Host

This will list all entries cached by Leopard, it can comes in handy when trying to solve a name resolution problem.

And finally if you want to get ride of your entry later on :

sudo dscl localhost -delete /Local/Default/Hosts/myvhost.loc

[Update 2008/01/07]
Benjamin Stiglitz wrote a comment to say /etc/hosts is now automatically watched for changes on Leopard, so there’s no more need to play with dscl to add simple host. Thanks again Benjamin.

Test::Unit interoperability : switch smoothly from Test::Unit to RSpec by allowing you to run your Test::Unit tests with RSpec. The goal here is to provide a way to progressively transition your tests to RSpec syntax.