Mining ActiveSupport: Object#returning
ActiveSupport is the unsung hero of Rails. Much of what makes Rails code beautiful and powerful is implemented in ActiveSupport. It adds numerous methods to many of the core classes, which are used throughout Rails. If you don’t mind digging around, you can find all kinds of handy tricks to use in your own applications.
Consider this common idiom:
1 2 3 4 5 6 7 |
def create_book book = Book.new book.title = "Trafalgar: The Nelson Touch" book.author = "David Howarth" @db.add(book) book end |
You create an object, set some properties on it, and then return the object. ActiveSupport adds a new method (called returning
) to Object, which can be used to beautify (and in some cases, simplify) that idiom:
1 2 3 4 5 6 7 |
def create_book returning Book.new do |book| book.title = "Trafalgar: The Nelson Touch" book.author = "David Howarth" @db.add(book) end end |
The latter is no shorter than the former, but it reads more elegantly. It feels more “Rubyish”. And there are times that it can save you a few lines of code, if that’s important. (Just scan the Rails source code for more examples.)
Object#returning
has been in Rails for quite some time, being checked in on March 20, 2005 in revision 949. (It now lives in active_support/core_ext/object/misc.rb, and behaves slightly differently than the original did, but it is still as brief as ever.)
Looking at the comment for that method, you’ll see it described as “A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman.”
In researching this article, I googled (pardon me, “searched Google”) for Mikael Brockman, to see just who this genius is. Unfortunately, though he seemed active enough in 2005, he appears to have fallen off the face of the Internet since then. At any rate: big props to Mr. Brockman for contributing this.
If you’re into functional programming at all, you probably know right away what the K combinator is. For the rest of us, this article is helpful (if a bit on the academic side, but that’s about par for the course for most reading about functional topics). Basically, the K combinator is a function of two arguments, that merely returns the first argument. The second argument is useful only for the side-effects it has on the first argument. The implementation of this in Ruby is beautifully succinct:
1 2 3 4 |
def returning(value) yield(value) value end |
It takes a value (the first argument), yields it to the associated block (the implicit second argument), and then returns the value. The block is used to operate on the first argument, and thus (by its side-effects) provides the actual work of this method.
It’s pretty handy!
Reader Comments
Nice tip! Thanks.
27 Oct 2006
In terms of this example, is the “returning” method really necessary? Wouldn’t the Book.new call leave the last object on the stack and thus get returned by the method? Or does the @db.add(book) mess this up somehow? Did I miss something?
27 Oct 2006
Doug, note that
Object#returning
is never “necessary”. It really more of an esthetic improvement, syntactic sugar.However, if you know that @db.add(book) will return book, you could just leave it as the last statement in the method and you’d be fine. You won’t always have that luxury, though, especially if you are dealing with code that you didn’t write, and which you don’t particularly care to monkeypatch.
27 Oct 2006
I’ve been looking for an explaination of this for some time now – I never knew it was part of Rails until now. Cheers!
27 Oct 2006
I’m still not sure if I’ll use it much in my code. It doesn’t save any typing, and I don’t think it simplifies everything (in fact, it makes future readers of your code be familiar with another function).
27 Oct 2006
A slight twist on this k combinator concept is when the first argument is “self”. Surprisingly useful.
class Object def tap yield self self end end
from http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions.html
27 Oct 2006
Thanks Jamis for this simple but wonderful tip! Seeing Brian’s last post, I made a handy “with” method, that combines both the “returning” and “tap” methods mentioned above into one. A nice little bit of syntactical sugar.
class Object def with(obj=self) yield(obj) obj end end
28 Oct 2006
IMO a simple ‘return book’ would make the code clearer and simplier. Maybe not more rubyish but I bet more people will understand it right away then the fancy example.
I never could understand why it’s considered good ruby style to not use the ‘return’ keyword. In some places it makes the code ugly but in others it makes it more readable.
28 Oct 2006
Wow, ask a question and get a whole post for a response. Thank you for taking the time to write this up Jamis, you do an excellent job of explaining the inner workings of Rails.
29 Oct 2006