Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Block/fu

Pivotal Labs
Wednesday, April 30, 2008

This is the second article on idiomatic Rubyisms that I like. Today’s snippet is also from ActiveRecord.

The following method takes :conditions arrays of the form ['foo_id = ?', foo.id] and turns them into safely quoted SQL strings:

    def replace_bind_variables(statement, values)
      ...
      bound = values.dup
      statement.gsub('?') { quote_bound_value(bound.shift) }
    end

The calling gsub with a block and shifting off of the bound values inside the block is so cute that I want to give it a hug. You know, I cut my teeth doing functional programming and I usually have this aversion to such a side-effect-heavy style. But treating gsub as an iterator — and using shift as a kind of index into the iteration — is so elegant you have to love it. It makes you remember that sometimes things are beautiful because they are imperative, not despite.

Of course, you could write this purely:

statement.gsub('?', '%%s') % values.map { |v| quote_bound_value(v) }

(I’m showing off here a bit with the % (percent) operator on String.) So this latter code is pure and it’s clear. It may even be more terse than the imperative version since it lacks the duping of the values array. But I don’t know about you but I don’t want to give this functional code a hug. The imperative version is like a baby panda bear:

Panda

Don’t you want to hug that? Whereas the Functional Version is like kind of like a Japanese carp.

If there’s any lesson from this it’s: know which standard library methods take a block.

Here is some code I hacked up recently somewhat in the spirit of the gsub-with-block approach above:

  [relation1[attribute], relation2[attribute]].select { |a| a =~ attribute }.min do |a1, a2|
    attribute % a1 <=> attribute % a2
  end

Don’t ask what this code does, it’s not what you think (this is operator overloading taken to its psychedelic conclusion). But note the use of min taking a block. This is the same as providing a custom ordering relation to sort, a pretty common idiom in many languages. But here I’m not interested in sorting attributes based on their intrinsic hashrocketness; rather, i need to sort them based on a comparison to some other object. min takes a block gsub takes a block sort takes a block… you’d be surprised at what takes a block. Look it up.

Now, I know some of you are going to say, “I did look it up, and that’s
not true.” That’s ’cause you looked it up in a book. Next time, look it
up in your gut.
— Stephen Colbert

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

One comment

  1. Dr Nic says:

    Oooh, I didn’t know gsub took a block. *rubs hands together*

    May 5, 2008 at 11:39 pm

Add New Comment Cancel reply

Your email address will not be published.

Pivotal Labs

Pivotal Labs

Recent Posts

  • Does the set of all sets contain itself?
  • Standup 3/8/2012
  • Standup 3/7/2012
Subscribe to Pivotal's Feed

Author Topics

riddles (1)
agile (167)
capistrano (2)
rails (26)
movember (1)
git (10)
railsdoc (1)
object-design (1)
bdd (3)
cucumber (3)
linkedin (1)
oauth (1)
ruby (17)
tdd (2)
lvh.me (1)
rails 3.1.1 (1)
selenium (6)
homebrew (1)
mysql (5)
rvm (1)
sproutcore (1)
paperclip (2)
pry (1)
amazon (1)
heroku (1)
rails3 (2)
jasmine (3)
design (3)
process (12)
productivity (8)
learning (1)
olin (1)
migrations (2)
mongodb (2)
devise (2)
javascript (13)
rubymine (4)
ipad (1)
whurl (1)
head.js (1)
pairing (2)
tools (4)
pair programming (1)
rspec (10)
rspec2 (1)
ruby19 (1)
incubation (3)
startup (5)
api (1)
presenter (1)
vanna (1)
pivotal tracker (5)
capybara (1)
fakeweb (1)
webmock (1)
intern (1)
ruby on rails (25)
meetup (1)
textmate (1)
testing (20)
solr (4)
nyc-standup (11)
community (1)
opensource (3)
activerecord (4)
chrome (1)
mp4 (1)
activeresource (1)
flash (3)
neo4j (1)
nginx (1)
rsoc (1)
meta programming (1)
agile standup (7)
government (3)
webos (4)
xss (1)
jquery (1)
bundler (2)
ci (3)
gems (5)
postgresql (1)
geminstaller (1)
gemcutter (1)
cloud (2)
rack (2)
refraction (1)
gem (5)
refactoring (1)
validations (1)
webrat (1)
engine-yard (1)
firefox (2)
jsunit (1)
mongrel (2)
thin (1)
unicorn (1)
facebook (1)
rubygems (5)
jruby (1)
actioncontroller (1)
rails 2.3 (1)
palmpre (1)
autotest (1)
mac (2)
hosting (1)
goruco (11)
database (3)
railsconf (11)
gogaruco (4)
deployment (4)
github (1)
ie (1)
ajax (1)
intellij (1)
json (1)
asset packaging (1)
polonium (1)
character encoding (1)
utf-8 (1)
test (3)
civics (1)
hpricot (1)
rake (3)
sms (1)
unicode (1)
iphone (1)
java (1)
safari (1)
memory leaks (1)
rr (3)
editor (1)
css (1)
nyc (3)
performance (5)
fun (5)
enterprise rails (1)
health (1)
new and cool (1)
general (2)
treetop (1)
errors (1)
stack (1)
trace (1)
cache (1)
cookies (1)
freesoftware (1)
conferences (1)
development (1)
driven (1)
proxy (1)
caching (1)
peertopatent (1)
languages (1)
rest (2)
rubyforge (1)
sake (1)
file (1)
upload (1)
constants (1)
osx (1)
terminal (1)
pairprogramming (2)
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >