I've been experimenting with Ruby 1.9.1 and trying to make it my natural home recently. Crucial to that was getting the mysql gem installed. Actually it's fairly straightforward with the 2.8.1 version of the gem and only very minor mods to the official instructions at http://www.tmtm.org/en/mysql/ruby/ were required.

Note that I have only tried this to work against MySQL 5.0.x, which I have installed in /usr/local/mysql, as all my previous attempts to use MySQL 5.1 have failed miserably and I've given up on that for now. These instructions install from source, resulting in a fresh /usr/local/ruby191/lib/ruby/site_ruby/1.9.1/mysql.bundle. Then you can simply require 'mysql' in your Ruby code and you're away.

  • Downloaded 2.8.1 source tgz from RubyForge, linked from http://www.tmtm.org/en/mysql/ruby/ downloads section.
  • Expanded the tgz with Finder, then opened a command prompt…
  • > cd mysql-ruby-2.8.1
  • > ruby extconf.rb –with-mysql-config=/usr/local/mysql/bin/mysql_config -with-mysql-dir=/usr/local/mysql
  • > make
  • > sudo make install
Et voila! Note that make did output a bunch of warnings about implicit 64/32 bit conversion that suggests the code isn't entirely 64 bit happy, but I've not observed any problems as a result. Yet.

I advise every programmer out there to read lots of other people’s code. Pick an open source project that you’re a fan of (and perhaps use every day), download the source and then sit and try and figure out how it works. You may find the following things:

  • It’s interesting to see how other people write code, from their specific syntactic style to the level of commenting, overall design and code layout, common idioms etc. You’ll probably learn something – either good things that you can copy, or bad things that are tough to read and warn you off doing the same.
  • You may find the code frustrating and difficult to figure out, not only initially but no matter who long you work through it, though if that’s the case then it’s probably poor code. Hopefully that will influence how you write your own code, for the better. 
  • If it is a product that you use regularly, you may gain insights into what it’s really doing and how, that empower you to use it more effectively. You may even be able to modify it to make some improvement that matters to you.
  • Once you’ve got past the initial difficulty and started to understand things, you acquire a sense of power. No longer are these complicated pieces of software opaque and mysterious. They can be broken down, understood and messed with. A whole world of possibilities opens up and you no longer need to be afraid. 

I’ve recently been reading the Ruby source code of Innate – the new underpinnings of next generation Ramaze, a Ruby web app framework that I particularly enjoy using. Innate is built on top of Rack, so I’ve been reading that too. The mystery is ebbing away and it’s making me more powerful. Stand back! 🙂

I've been following the progress of MacRuby for a few months now and was looking forward to the next release. Finally, and a month or three after it was expected, MacRuby 0.4 is here, according to the MacRuby blog.

MacRuby is, to keep it simple, an implementation of Ruby 1.9 built in Objective-C with transparent calling between the ruby and Obj-C worlds. For instance Ruby Strings are actually NSStrings in MacRuby and have all the powers of both. This along with some other neat integrations provided by the team allow you to write Mac OS X Cocoa apps using Ruby instead of Obj-C, or even a combination of both. If like me you think that Obj-C is a dinosaur that doesn't deserve a place in the modern programming world, this is great news. There seems to be a lot of momentum behind this project and I wonder if it may eventually become quite a fully fledged citizen for Mac app programmers – maybe even ultimately taking over from Obj-C for most Mac OS X development. I can but hope.

One of the many neat improvements in 0.4 is the ability to bundle the MacRuby runtime into the app itself so the user need be none the wiser, and certainly doesn't need to install MacRuby.

I was running into an annoyance whereby I'd end up with duplicated validation messages from ActiveRecord. I tracked this down to the source reload feature of Ramaze, which was reloading my AR model classes each time I edited them with the dev server running, which has the unfortunate side effect of adding the validators again on top of the same ones that were there before. So each reload adds another set of validators and another duplicate validation message. This sort of thing (mainly class methods that add to a list) often requires special care when working with a source reloading system. In this case I've worked around it by resetting AR's internal validator list to empty before creating my validators, by directly accessing the @validate_callbacks instance variable. For example:

class Event < ActiveRecord::Base
    # Clear all AR validations, to avoid getting duplicates on source reload.
    @validate_callbacks = []
    validates_presence_of :name
    validates_presence_of :description
end

Did you know that you can simply type "gem server" at your command line to start up a web server on port 8808 that presents all the built-in documentation for your installed gems?

This seems to be a little known fact among Ruby programmers, but worth a lot I reckon. I have rediscovered this feature a couple of times and it's enormously useful, especially when working on the train so having to rely on local documentation. It certainly beats ri for many things.

Picture 6
Oh and that's the new Safari 4 beta, if you're confused by the look of the browser window in this screenshot!

I've been furiously porting my Ramaze CRUD helper from DataMapper to ActiveRecord and I've been quite surprised to find that it's only taken a couple of hours. I should hastily point out for non-programmer types, that CRUD stands for Create Read Update Delete – the four basic operations you can perform on a data entity.

My helper makes it super-easy to produce basic CRUD web pages for any data entity, with just a couple of lines of code in your helper – a bit like Rails scaffolds but without the scaffolding! Sounds like magic, I hear you yell! Well yes, but it's my magic that I wrote from scratch so it's not magic to me 🙂

It's been an easy port between ORMs mostly because the concepts and syntax map over with relatively little fuss, and actually 98% of my CRUD helper code is not concerned with the DB, but rather with running the web UI. So the few places that actually perform a DB operation needed a bit of tweaking to use the right syntax, but it's been pretty smooth sailing. Hopefully it will be easier with AR to neatly deal with many-to-many associations without having to explicitly fool around with the join table. We shall see, as that's what foxed me with DataMapper and caused me to switch.

One very important thing to mention is that when using ActiveRecord outside of Rails you have to know that it was originally written for the single-threaded Rails world. Hence it just maintains a very small connection pool (say 3) and those connections quickly run out in a threaded environment – Ramaze in my case. This leads to strange pauses of several seconds as your request handling thread waits for a connection to come free. They come free after about 5 seconds of inactivity, so you get one reasonably soon, but the multi-second pause is infuriating and very confusing. A neatly packaged solution is handily presented and well explained here: http://coderrr.wordpress.com/2009/01/16/monkey-patching-activerecord-to-automatically-release-connections/. Note that there is a link at the bottom to the single-file patch that just sorts everything out for you, so if you can't be bothered to read the explanations, head straight for that, require it in your project and you're away.

I've spent a bit more time learning Python, because I've been dabbling with Google App Engine (which I'm going off rapidly) but mainly because it's an interesting language. What's particularly intriguing to me is its similarity to Ruby, and hence where it differs in syntax or approach makes for a notable point of comparison. Of course it's probably more correct to say that Ruby is similar to Python than the other way around. From my still very small exposure to Python…

Nice things about Python:
  • Less confusion with the way classes work. Or maybe I just haven't stumbled into Python's equivalent of meta-classes and class vs instance variables.
  • @classmethod is a much neater way of stating what's a class method rather than an instance method, compared to all that self gubbins, or the dreaded <<.
  • Optional named arguments for functions, allowing more flexibility for optional arguments and greater clarity when calling. [As an aside I like Objective-C's way of building argument labels into the method signature, but not it's square brackety syntax: [obj message:foo]. I'd much rather do obj.message(foo) and in fact with properties in Objective-C 2.0 we see more of this style.]
  • I think I probably prefer explicit return statements rather than the Ruby way of returning the last evaluated thing in any expression.
  • List comprehensions. To start with it just seems like a syntactic difference – Python: [x*2 for x in my_list]  Ruby: my_list.map {|x| x*2}. But Python's party trick is excluding elements as it goes: [x*2 for x in my_list if x != 3].

Nasty things about Python:

  • Seriously – indentation to demarcate blocks? Apparently I'll get used to it.
  • Double underscores. __init__ is a complete pain to type. Why not just a single underscore at the start or something?
  • Fiddly module system. Why the need for an __init__.py file in a directory, just to make it a module? Why the need to explicitly define an __all__ method just to be able to import everything in a module? I want to be able to create a "model/" directory, put all the .py files for my DB classes in there, then import the whole lot from my other classes with ease. When I add a new model class, I shouldn't have to go and modify the __init__.py file. It seems to be a real pain to split code up into multiple files sensibly in Python. If I've missed a trick here – please somebody show me the light!
  • The string interpolation is OK I suppose, giving the full power of C style formatting, but most of the time you're just doing simple interpolation and Ruby's syntax is far more pleasant and readable. Python: "Hello %s, from %s." % (person, greeter)  Ruby: "Hello {person}, from {greeter}."  Ruby also has a full on formatting system for the few times when you need it.

  

It seems to be the done thing these days to learn how to use Google App Engine (and thus Python) within a couple of hours and then hack out a simple web application to prove how easy it is.

So with the missus out of town tonight, I'm staying out of trouble by doing just that. I've run through the getting started tutorial, which is a delight I have to say, especially because it's so darned simple to get going on Mac OS X. Python is already installed and there's a neat app to download from Google which installs the app engine SDK bits and puts a nice GUI front end on it for you to fire up the local test environment and various other handy things, as well as installing the command line tools if you prefer them. Start up TextMate or any other editor of your choice and you're away!

You'll have to take my word for it though, because I'm tired and won't get onto writing my own app tonight.

Footnote: Python seems OK, but so far I prefer Ruby, though they seem to share a lot in common.

I’ve been happily beavering away with the stock install of 1.8.6 on Mac OS X 10.5, but it seemed like everyone was moving on to Ruby 1.9 so I thought I’d make the leap. Was it a good idea? More on that later, but first here’s how I successfully installed it on my MacBook, based on instructions from http://hivelogic.com/articles/2007/02/ruby-rails-mongrel-mysql-osx. That page has a good detailed commentary of what’s going on, but didn’t actually work correctly for me, perhaps because of recent changes to the code in question. My version is short and sweet too, for those that either don’t care for the whys and wherefores, or find the command lines self-documenting enough.

Ruby 1.9 Install Instructions

Note: following these instructions will install new ruby and irb binaries in /usr/local/bin. The old system versions will still exist in /usr/bin/, but the new ones will take precedence by virtue of the PATH setup noted below.

  1. Ensure the following is at end of your ~/.bash_login:
    export PATH=”/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:$PATH”

  2. Reload that modified file so your environment picks it up (or just open a new terminal):
    > source ~/.bash_login

  3. Download and install libreadline.dylib as follows:
    > curl -O ftp://ftp.gnu.org/gnu/readline/readline-5.1.tar.gz
    > tar xzvf readline-5.1.tar.gz
    > cd readline-5.1
    > ./configure –prefix=/usr/local
    > make CPPFLAGS=-DNEED_EXTERN_PC SHOBJ_LDFLAGS=-dynamiclib
    > sudo make install

  4. Download and install latest Ruby 1.9 (or instead of living on the bleeding edge, download a tar of a stable source tree from http://www.ruby-lang.org/en/downloads/ in place of the first step below):
    > svn co http://svn.ruby-lang.org/repos/ruby/trunk ruby_trunk
    > cd ruby_trunk
    > autoconf
    > ./configure –prefix=/usr/local –enable-pthread –with-readline-dir=/usr/local –enable-shared
    > make
    > sudo make install

That’s it! Now assuming your PATH is setup as above, ruby –version should report 1.9. If not, check that ‘which ruby’ reports /usr/local/bin/ruby.

So What Next?

What next indeed! I thought I’d try and run a simple ruby app of mine to see if it worked. It didn’t, but that’s because the new ruby install keeps its gems in a different location and its cupboard was bare. I set out to reinstall the gems I needed, but I ran into some problems. Some gems just won’t install, because they have C extensions that are incompatible with Ruby 1.9 so they fail to compile during gem install. Others installed fine but then failed at runtime due to Ruby compatibility issues. There’s a great page with the major porting tips at http://boga.wordpress.com/2008/04/15/ruby-19-porting-notes/ which helped me fix most of the Ruby issues. Here’s a breakdown of my struggles:

  • Ramaze worked great as it’s been 1.9 compatible for ages.
  • The mysql gem only installed successfully by downloading the 2.8pre4 code from http://tmtm.org/downloads/mysql/ruby/ and following the install instructions.
  • The tens of gems that constitute DataMapper (my current ORM of choice) struggled. I was able to make simple Ruby changes to fix many bits, but I ran into real issues getting the database adapter gems do_mysql and do_sqlite3 to install as their C extensions are incompatible.
  • I don’t think my own code ever really got to run, so I have no idea if it’s good or not. I suspect it’s fine or requires minimal Ruby mods.

So I ran out of time and gave up as I’ve never gotten into the C extension side of things before and didn’t fancy starting. Perhaps I’d be able to sort it out if I put the time and effort in.

Overall it’s shown me that Ruby 1.9 is only worth the effort if all the gems you require are already compatible. I kind of already knew that before I embarked on this mission, but hoped that I’d be pleasantly surprised, or be able to do the porting myself with minimal effort. I was a bit disappointed to find things lagging behind as I assumed the Ruby community were eager technologists always at the forefront of each new thing! Maybe people are too busy coding solutions to their real world problems to bother with 1.9 until it’s declared official (late 2008 at last mention). I also get the impression they’ve become jaded with the extremely long gestation period for this release. Maybe I’ll try 1.8.7. One step at a time.