Dr Nic

Composite Primary Keys goes 1.0.0 for Rails 2.1

Two years ago Dave Thomas did a keynote at the first RailsConf in 2006 and outlined a few things missing in Rails. One was the seeming unnecessary un-DRYness of duplicating associations and validations in Active Record models since the same information is in the DB schema. Another was support for Composite Primary Keys on Active Record models.

A few weeks later I created my first RubyGems as an attempt to solve these problems: Dr Nic’s Magic Models and Composite Primary Keys. The former was funny and an entertaining way to use const_missing? and Class.new. The latter was not funny. It started at the heights of “mildly entertaining,” dropped down from there and then over the subsequent months it never again rose above the humour-scale heights of “please shoot me in the foot.”

There were entire months that I hated ever having created the Composite Primary Keys project :)

Why? It sits precariously atop of ActiveRecord::Base, and a half dozen other ActiveRecord classes. It overrides methods, recreates entire blocks of SQL, and must work on all the different database adapters. That is, it is very sensitive to many changes in edge Rails. And refactoring ActiveRecord is a favourite pastime of the Rails Core team.

Unlike the Magic Models project which is perfectly useful for party tricks but probably partially pointless elsewhere, the CPK project just seemed to be so damned useful to some people.

Many people kept using it, several people contributed patches for adapter support and new features, and finally the Prophet arrived. The man that would lead the faithful forward to the Promised Land.

His name is Darrin “Champion” Holst.

Today, CPK was given the golden release number 1.0.0 and officially supports Rails 2.1 (but no longer supports 2.0.2 afaik).

CPK users might remember that we went 0.9.90 back in January, and its now June. This led Darrin to comment in his release email to the mailing list:

I’d like to name this release the “we’re running out of 0.9.x numbers, so it has to go to 1.0 sooner or later” release.

Maintaining CPK is like being on the team that paints the Sydney Harbour Bridge – it takes then 12 mths to paint it from one end to the other, which is just in time to restart painting the bloody thing again.

So in every way that I (tried to) abandon the project, I am proud of Darrin for looking after it and all its users.

An Interview with Dr Nic

Do you want answers to questions like:

  • What do you think about the current Twitter vs DHH discussion?
  • How did you come by with the Magic Model solution?
  • What does the New Gem Generator actually do?
  • Will we see ‘Rails Distros’ in the long run?
  • Where are you from? What’s your current day job, is it Rails related? And what’s your history with Rails?
  • Did you get your free t-shirt?

Brazilian Fabio Akita – author of the first Brazilian book on Ruby on Rails also wanted to know, so he asked.

Thanks to my friend Carlos Eduardo for teeing it up.

Go to interview

Magic Models: the Spring collection

Over the last few months, we at Dr Nic Magic Models (Sweden) Inc. have been gradually selling down all the company shares to pension funds at over-inflated prices, whilst at the same time refusing to release new patches for old projects that sorely need them – Composite Primary Keys and Dr Nic’s Magic Models.

Magic Models 0.8.0 exhibited range of wacky behaviour and I’ve been suggesting people 0.7.2 for a long time, instead of releasing 0.9.0, which I mostly wrote last year.

I received a huge patch for Composite Primary Keys in my inbox in February and despite the emails of “when will this patch be released” by the punters, I sat on it.

I’ve also mentioned in emails several new projects that I’ve either never released or they are lurking on RubyForge without any celebratory fanfare. For example, the Magic Model Generator – got 200 tables in a legacy schema? Generate 200 model files in 20 seconds.

The share price has now plummeted, and over Easter I bought back all the shares at half price. All that’s left to do now is unveil a barrage of new projects and releases and watch the share price soar. Booya.

So, over the next week or so, you will be treated to:

Magic Models by Dr Nic - Spring

So call the babysitter, grab yourself a champagne, and find a seat in front of the catwalk: its show time.

Remote Shell with Ruby

I wrote Composite Primary Keys and Dr Nic’s Magic Models because we have a 50+ table legacy database and I am terrorised by explicit SQL statements on a daily basis. I have a dirty secret – I don’t use either of them at work. We’ve been unsuccessful installing Ruby on our HP-UX box, then time passed, life moved on for the people involved, and so no Ruby. Ergo, SQL hell for Nicholas.

Until today. No, we still don’t have Ruby installed on our HP box, but I do have it installed everywhere else in my life. So I guess I can still access the database remotely… that’s what the TCP/IP internet protocol is for… and for executing shell commands why not remote shell into the box?

Let’s skip over why I never thought of either of these until now. Its bad for my ego. The upside of this minor revelation is that the Composite Primary Keys project will have Oracle support soon.

Remote Shell

The point of this article though is to discuss the wonders of using remote ssh (aka remote shell) to invoke shell commands via ruby without having ruby installed locally.

I made it work, it rocks and I shall briefly sing the praises for Jamis Buck. Jamis, you rock. net-ssh is a lovely API for performing remote shell commands all from ruby. Here’s a demo of what I can do (excluding the setup code which is discussed later):

>> print shell.pwd.stdout
>> shell.cd 'demo'
=> #<struct Net::SSH::Service::Shell::SyncShell::CommandOutput stdout="", stderr=nil, status=0>
>> out = shell.ls '-lart'; print out.stdout
total 16
drwxr-xr-x   2 senwilli   sv              96 Sep 22 11:56 .
drwxr-xr-x   5 senwilli   sv            8192 Sep 22 11:56 ..
>> out = shell.send_command 'ls -lart'; print out.stdout
total 16
drwxr-xr-x   2 senwilli   sv              96 Sep 22 11:56 .
drwxr-xr-x   5 senwilli   sv            8192 Sep 22 11:56 ..

I’ve deliberately been inconsistent in the way I called the shell commands and how I handled the responses to show you some interesting things.

shell is our shell object (which we’ll cover in a bit) and it has delightfully overridden method_missing so I can send it any old shell command I like. In the example above, I call the commands: pwd, cd and ls using this method. The first parameter is the arguments you’d like to pass to the command. An optional second parameter is for any stdin you’d like to pass to the process during its execution.

The last command is a duplicate of the previous command, showing that you can explicitly pass a complete shell expression string via the send_command method.

The result of all shell commands is a struct containing stdout and stderr strings. So, to return the response of the command to the user or logger, you’ll need to store the response object (as per the out variable above) and use stdout? to test if stdout has anything in it.

In the example above, all these commands are executedly being executed synchronously, so I’m getting the stdout/stderr results back before the next command is executed. This is due to the way I created the Shell object. So, let’s look at that.

Creating your Shell object

First you’ll need to install the following gems (from rubyforge.org) in this order: needle, oepnssl, and net-ssh.

In your ruby script/console:

require 'net/ssh'

session = Net::SSH.start( 'host', 'user', 'passwd' )

To create our synchronous shell:

shell = session.shell.sync

And you’re off and racing.

Jamis has provided lots of useful syntatic sugar (for example, you can pass Net::SSH.start a block with session as its argument, and reading all the docco is a clever thing to do next.

Using sudo?

The only thing I couldn’t immediately figure out is how to invoke sudo su - envname and then continue to control my shell as per normal. All commands just blocked.

Luckily there is a mailing list for me to loiter in…

Composite migrations for Composite Primary Keys

The good people at Err-the-Blog were almost satisfied with the humble offerings of Composite Primary Keys, which provide composite key support for ActiveRecords, including composite foreign keys in assocations. They’ve gone on an published the main remaining requested feature – composite migrations for your database table changes.

Errtheblog – Composite Migrations

Now, this means that if you want to use composite foreign keys because you like them you can create as many as you like and DHH can’t make it hard for you. :P