So, in response to an earlier post, “mexx” asks:

Let’s say that I have a class BigTree and I have a string ‘big_tree’ how do you get the string translated to ‘BigTree’ so that I can use this translated string the way you showed?

That’s a fun challenge. Well, as I’ll later show, it’s a problem to which I already know the answer. But I gave it a shot, and came up with this – my first genuine, off-the-top-of-my-head one-liner (and I wasn’t golfing):

def camelize(str)
  str.split('_').map {|w| w.capitalize}.join
end

That’s a bit cryptic. To decode it, if Ruby’s not your first language:

  1. Take a string
  2. Split it on underscore characters into an array
  3. Capitalize each item in the array in turn (which I do by mapping the array to a new array, with the built-in String method capitalize)
  4. …and then join the whole array back into a string

Unfortunately, that works for mexxx’s example – big_tree will map to BigTree but it’s certainly not true for all possible classnames.

But, as I said earlier, I already know the answer to this. It’s part of Rails – specifically, it’s in the Inflector component of ActiveSupport. Go to the API docs and look for “camelize”. Most of the Inflector components are dependent on each other; camelize, fortunately, is only dependent on itself. And it looks like this:

def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
  if first_letter_in_uppercase
    lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
  else
    lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
  end
end

That looks a whole lot more convincing and generic. And I think that’s your answer, mexxx. So don’t thank me – thank the Rails core team. There’s lots of useful basic Ruby tools hidden in the Rails sourcecode – it’s always worth an explore, if only to find out more about how it does its stuff.

Didn’t notice this when it happened (because it didn’t necessarily appear on the frontpage) but… my review of David Black’s Ruby for Rails has now gone live over at Vitamin.

My first piece of technical writing. It’s a good book, too – clarified an awful lot about the hierachy of classes within the language, and explained the nuances of Ruby dynamism very well; strongly recommended to anyone coming to Ruby (through Rails) afresh, whether you’re an experienced programmer or not. I hope I conveyed that in the review.

Matt posted a really elegant piece of code today that generates Graphviz files (suitable for importing into OmniGraffle) of your Rails ActiveRecord relationships. It’s pretty neat, and certainly handy for getting to know foreign codebases.

There’s one neat trick in there, though, that I wanted to expand on, as Matt breifly chatted to me about the problem earlier today over IM – namely, how you get the actual class object so that you can call reflect_on_all_associations on it.

In Ruby, it’s easy to dynamically call methods – you can put the name of the method into a string, and then simply run Object.send(methodname). Getting the actual Class Object for a particular object – that’s much trickier.

There’s the obvious solution of using eval. So, to get all the methods on your classname:

classname = 'Integer'
eval classname + '.methods'

but that, of course, is pretty nasty and kludgy. This is Ruby, after all; there’s got to be a better solution, right?

There is. If you look in the Pickaxe, you’ll find that Class Names Are Constants:

All the built-in classes, along with the classes you define, have a corresponding global constant with the same name as the class.

So this means that by passing the class name to the const_get method on the Kernel module, we’ll confirm if a class exists with that name (eg Integer). Then, because that constant is really a reference to an object of the same name, by sending a message (the method calal) to the constant, it will be passed on to the object and run (which is the best way I’ve got of explaining this). Job done! To use the previous example:

classname = 'Integer'
Kernel.const_get(classname).methods

Which is, you must admit, a bit more elegant and maintainable than the evil that is eval.

A quick heads-up to two brief speaking engagments I’ve got coming up on the horizon.

First, I’ll be talking about software to tell stories with at the London Techa Kucha night on 25th July that Steve and Tom are running. That’ll be a radio-edit of the talk I gave at Reboot, more or less.

Then, I’ll be talking at LRUG on August 8th, looking at how as a Rails developer you can work effectively with front-end designers and client-side developers, and how you can keep the integrity of your front-end code at the same level as the back-end.

Come along if you feel like it. And if you found out about these events through the blog, do say hi.

So I’ve been fiddling with Rio recently. I’m trying to write a little script to find and replace throughout a directory – and all its subdirectories, recursively. Given the end result of this might end up being an application based upon Rails, it seemed best to write this in Ruby. And I remembered someone (Tiest, I think) mentioning Rio at one of the LRUG meetings. So I gave it a shot.

Rio is, in short, lovely. It acts as a convenience wrapper around a whole host of modules – including Kernel, File, Dir, and others – and basically makes reading and writing files a doddle. It’s also quite powerful, and makes batch operations across directories really easy, once you’ve figured it out.

So my global find/replace script comes down to this:

rio('dirname').all.files.skip(/^\./).do |eachfile|
   eachfile < eachfile.contents.gsub("search", "replace") end

And that's it. Obviously, this being gsub, "search" can be replaced with any regular expression of your choosing. I'm sure I could do it faster in sed/awk/grep, but I'm not as familiar with them as many - and this way around, I can patch this snippet into a larger Ruby application. The skip clause forces Rio to ignore files beginning with a dot, as .DS_Store and friends cause it problems (it seems).

Anyhow, I'm very impressed with Rio - saves a lot of faffing with read and write modes - and can highly recommend it if you need to faff with the file system in Ruby.

Rails and Hypercard

22 December 2005

Gavin mentions the idea that Ruby on Rails might just be the new Hypercard – something I may or may not have discussed with him.

I think he’s right. After one of the London Ruby User Group meets, someone commented that all Rails really needs now is a killer easy-front-end for page layout, or an IDE for apps of some form, and it could really hit the jackpot. I immediately thought of Hypercard; it had the requisite simplicity, grace, and convention, and would be nicely suited to Ruby (just as it was to Applescript).

I’ve mentioned Hypercard before on this site. It was pretty formative in me finding a way I could program computers that wasn’t necessarily reams of code, of first making me aware of UI design, and of making programming fun. Rails has had a similar effect, properly kick-starting me into OO programming, and finally making me understanding and appreciate scripting languages.

The speed of gettings things working, that’s what matters. Not finished – finished might be a long way off – but you’ve always got something to show for your labours. That’s why I like it.

It’s.. the Visual Studio 2005 song! From Microsoft Korea; it’s catchy, awesome, and has a great flash animation. The product clearly can’t live up to the song. All together now: “Visual! Studio! Team! System!

Brain slowly changing gear

08 November 2005

A short while later, and I’m slowly shifting up, back out of holiday mode. The 280-odd new posts in NetNewsWire are all out of the way. Some interesting stuff – in particular, MacDara’s new look, which is interesting and a little niggling, as it’s a fair bit of the way toward where infovore should be shortly going (though mine will be slightly less chaotically ‘tumbly’) – and also Matt’s recent work for the BBC, which he mentioned at the last Rails/Django meetup. It’s a shame that the London Web Frameworks Day is full – it wasn’t open for registration prior to the holiday, and I’m a bit peeved it’s full. Ah well, there’s still the usual meetup.

My brain’s also beginning to buzz a little, following a whole lot of exciting ideas I had on holiday. Now I’m back, I’ve got the tools to realise them, and also a few more things on the backburner, and it’s all a little bewildering. I’m sure a night’s sleep and a day at work will bring clarity – and a short sharp dose of reality.

OK, so maybe I was a little hasty with my earlier post. We are emphatically not all developers now. The hyperbole ran away with me, and I apologise for that. But there was a nugget of truth in there.

If the Rails-revolution (and that includes all those things which perform similar functions to Rails, even if they themselves are not rails) has a real-world analogue, it’s that of the far eastern bespoke tailors. You see their ads in the papers; they fly over to London for fittings in hotels, and then make a bespoke suit for you in their workshops back in Hong Kong. You end up paying the price of a decent off-the-peg suit (about £200) for something tailored to you. Of course, it’s not quite Saville Row, but it’s still a darn sight better than a generic off-the-peg model.

And this is what the rapid-development-frameworks give to small businesses.

A small business wanting to serve the global market might consider, say, an online shop as part of its web presence. A small, local web-development firm are contracted to build one. A long while ago, said web shop built a fairly substantial (and customizable) online store. They now use this work as a basis for future stores – pull another copy off the shelf, add a few tweaks, and serve to client. To create something uniquely tailored to the client’s needs would take a lot of time – and the client, being a small business, can’t afford the time a bespoke product takes.

So they receive delivery of a store that works, but has quirks that they could do without, features they don’t need, and might even lack features that could save them time; instead, they implement workflow-based workarounds to those missing features.

What the new frameworks do is put bespoke products (especially small bespoke products) within reach of small businesses. A small web-development firm isn’t going to be overworked, or take too long, to start from scratch and create a product that is 100% suitable for the client. The client will be more productive as a result. It’ll probably be a better product, too, as the product will always be built to current standards (instead of being last year’s model, dolled up).

Of course, in this new bespoke-economy, there will still be successful web-development firms who continue to serve up the old, 90%-suitable, off-the-shelf product. They might get away with this for a while, but not forever, because the bespoke economy serves everyone better – developers get the chance to constantly be creating new things; clients get the product they’ve always wanted.

So we’re not all developers, we’re just all in a position to get bespoke development at off-the-peg prices (or less). I mentioned ‘software scaling down to a userbase of one’. It’s not that this is possible – it always has been – that makes these new development frameworks exciting, but that it’s suddenly become very, very viable.

Why should it scale?

24 October 2005

The big question around Rails: does it scale?

I say: forget that. Ask this instead: why should it scale?

Rails empowers the lowliest user or homesteader to create applications faster, at a lower cost than ever before. You may have an application that does 75% of what I want to do – but given that Rails puts t even closer to 0 it’s probably be faster for me to start from scratch than it is to try and adapt yours. That way, you have a perfect personalised solution, and so do I. If we looked at our code, they might even resemble each other a little. That’s survival of the fittest, isn’t it?

More and more users will become programmers as the tools, the middleware, the software-to-make-software gets better. Ning is the beginning of this. Users don’t need a generic solution; they’ll all be rolling their own. Software will become more discrete – hell, it’s going to become discerning. The tools we use are very personal; in an ideal world, they’d all scale to a userbase of one.

I guess that we’re all developers now.