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:
- Take a string
- Split it on underscore characters into an array
- 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
) - …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.
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.