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.

3 comments on this entry.

  • mexxx | 11 Aug 2006

    Thnx Tom,

    I was hoping that I could find something like camelize in ruby core libraries, since what I needed was something similar to translating rb file name to class name. But rails way works for me too :)

  • Chris Hoeppner | 28 Nov 2008

    That regular expression means nothing to me, to be honest, I’ll have to dig out my regexp reference book for that.

    How would you take on doing it the other way around, I wonder?

    def uncamelize(s)
    # Please gimme input :P
    end

  • Tom | 30 Nov 2008

    Again, Chris, the answer lies in ActiveSupport::Inflector; to convert camelized text to underscore-separated text, there’s a method called underscore, the source code for which can be found here. Hope that helps.