Ruby muckin
February 12th, 2008
So I was writing a Rakefile and found myself doing stuff like this:
cmd = "svn co #{src} #{dest}"
puts cmd
system cmd
Everytime I wrote lines like this, a little corner of my heart died.
I dreamt of something like this:
"svn co #{src} #{dest}".to :puts, :system
But it's hard to do this properly, because you need to get hold of the receiver (in the above case main, or some Rake task) or binding, so that the methods can be sent where they ought. With crippled Kernel#caller, the the demise of Binding.of_caller (Ruby-debug solved the problem but there's significant overhead) it was looking like I should just wait for the next ruby release.
But I frowned like Hiro and came up with this:
pass("svn co #{src} #{dest}").to :puts, :system
Briefly, Object gets #pass which creates a PassProxy (basic object). It keeps hold of the receiver, but acts like the object (in this case the string). When you send #to(:method) to this PassProxy, it calls the original receiver with the object.
This is just sugar, but its nice sugar in some cases. Compare:
# plain ruby
msg = "oooh!"
MyObj.foo msg
MyObj.far msg
MyObj.faz msg
msg
# => 'oooh!'
# returning (ActiveSupport)
returning "oooh!" do |s|
MyObj.foo s
MyObj.far s
MyObj.faz s
end
# => 'oooh!'
# (pass) (this code)
MyObj.pass("oooh!").to :foo, :far, :faz
# => 'oooh!'
But eat too much sugar and your teeth will fall out: I realised that this probably has limited usefulness (how often do you need to send the same object to a bunch of different methods?). But at least I learned some things in that last couple of hours of coding.
Go get the code from pastie if you're interested.
Thanks for reading
April 18th, 2008 at 12:03 PM Hey dude, Not bad Ruby - my head hurts trying to get around it and all. Kwak