5 Core Extension Tips
April 28th, 2008We’re all familiar with Rails’ core extensions. They’re the Ruby class extensions that allow you do things like:
"octopus".pluralize
["Lifeson", "rocks", "hard."].to_sentence
Now, I often find myself writing Rails helper methods that act on Ruby classes (String, Array, etc.). But to keep my code clean, I like to refactor these helpers as core extensions. This is a useful refactoring pattern for Rails applications. We might call it
- Replace Core Class Helper with Core Extension.
I’m going to show you how to include core extensions in your Rails app. Then, I’ll describe four extensions that I commonly use.
1. Write Your Own Core Extensions
First, create a module, name it core_extensions.rb, and store it in your /lib folder.
end
Then, at the very end of your environment.rb file, require the CoreExtensions module.
2. Format a string as a possessive.
These two methods extend the String class. The first returns the last character of a string. The second produces the possessive (’s) form.
def last
self[self.length-1].chr
end
def possessive
self.last == 's' ? (self + "\'") : (self + "\'s")
end
end
Here’s how it works:
=> "e"
"Joe".possessive
=> "Joe's"
3. Format Time as Month / Day / Year
Times needs to be formatted in all kinds of ways. Here’s just one example:
def m_d_y
self.strftime("%B %d, %Y")
end
end
And it works like so:
=> "April 28, 2008"
4. Display an array of ActiveRecord objects.
It is often necessary to iterate through an array of ActiveRecord objects, surrounding each with an html tag. Here’s an extension to array to automate this:
def each_with_tag(start_tag, end_tag, attribute)
to_display = []
self.each do |element|
if element.respond_to?(attribute)
to_display << (start_tag + element.send(attribute) + end_tag)
else
raise ArgumentError, "object does not respond to #{attribute}"
end
end
return to_display.join("\n")
end
How does it work? Say you have a recipe application. You need to display a list of recipe titles, each within a paragraph element:
=> "<p>Spinach Lasagna</p>"
"<p>Raspberry Tart</p>"
5. Get class name as string.
Here’s a simple method that comes in handy when using inheritance. Sometimes, you just don’t know what sort of object you’re dealing with. The class_name method does just what it says, giving you an easy way to display information about your object.
def class_name
self.class.to_s.downcase
end
end
Suppose I have a class modeling vegetables in a garden. If I needed to display a message about a particular vegetable, I could use class_name like so:
=> "A tomato should be watered two times per week."
Summary
Next time you write a helper that acts on a basic Ruby class, consider writing a core extension instead. Using core extensions can help create more elegant, portable, maintainable code.
July 7th, 2008 at 1:05 pm
Thanks for your possessive() function idea - it’s exactly what I was looking for.
Per the class_name idea, Ruby also supports obj.class.name which side-steps the need for to_s(). For instance:
x = {}
x.class.name
July 7th, 2008 at 7:44 pm
Chris,
I’m glad the possessive method was helpful. And thanks for the class name tip.
Cheers