Returning data from a Ruby block

Posted by Nicholas Sun, 22 Oct 2006 04:18:00 GMT

I have this little nugget of information that I discovered many months ago, but I’d always had a fairly easy time keeping it to myself as I wasn’t yet powering the internet with my blog.

However, now that I have a canvas with which to paint crap on, I figure now is as good a time as any to hip some fellow developers to a pretty useful and undocumented (or maybe everyone already knows what it is to the point that nothing needs to be said) feature of Ruby.

Have you ever been in the fairly common situation where you wanted to return data from the middle of a block? Something like this:
  [ 1, 2, 3, 4 ].each do |item|
    return item if ( item % 3 ).zero?
  end

Now, that seems logical enough, but most Ruby programmers will be able to spot right away that you’ll receive a LocalJumpError from the invalid return.

The solution for this is fairly simple. You can pass data after the break keyword that will be the return value of the block. For instance:
  [ 1, 2, 3, 4 ].each do |item|
    break item if ( item % 3 ).zero?
  end
Would indeed return 3. The above examples seem extremely useless, but where this feature really shines is in situations where you need to view the first element in a structure and the only methods available to you are each or some other iterator. For instance, I’ve used this extensively on classes that return stupidly large amounts of data in their inspect method. Such as most of the Spreadsheets or Graphics libraries for Ruby. Or you could also do ludicrous stuff like this:
  ObjectSpace.each_object( ActionController::Base ) do |controller|
    break controller
  end

This would give you only the very first instance of ActionController::Base, which could be useful in cases where you need to inject some data into a controller, or use some of it’s fancy methods without having to go through all of the problems associated with trying to start a new controller from irb. I know there are probably a million and one better ways to accomplish the same thing, but this one illustrates my point nicely.

A couple of months ago, a friend of mine blogged about returning from partials. Although it’s not the same thing, it feels very similar to me, in that it’s extremely handy to be aware of, yet it’s not documented anywhere.

Comments

(leave url/email »)