Our Daily Method #10: Object#r[rs][ds]s

Geplaatst door Michiel de Mare ma, 18 feb 2008 08:00:00 GMT

Ruby 1.9 has Object#tap. Danny introduced Object#with a long time ago. Then there’s Object#instance_eval.

Do these methods have anything in common, except for the inscrutability of their names?

It turns out that they do. These methods fall in the family of methods that:
  1. Are defined for any Object
  2. Take a block and always execute it once
  3. Don’t do anything else

So it may seem amazing that there are as much as three methods in this category. Actually, there’s even a fourth!

You see, even within these strict specs there are two decisions that we have to take.
  1. What do we return? The object itself? Or the result of the block?
  2. Within the block, what is self? Is it the object? Or is it unchanged (so we need to pass on the object as an argument)?
How do the methods we referred to earlier stack up?
  • tap: returns result, same self in block
  • with: return self, same self in block
  • instance_eval: returns result, different self in block.
And the Missing Method:
  • switch: returns self, different self in block.

Let’s see these methods in action!

name = group.owner.name
name = "bar" if name =~ /foo/
name.split(' ')

# with with
group.owner.name.with {|n| n =~ /foo/ ? 'bar' : n}.split(' ')

b = foo.bar
raise unless b

# with tap
foo.bar.tap{|o| raise unless o}.baz.goo

p = user.instance_variable_get("@secret")
user.instance_variable_set("@secret", p + "1")

# with instance_eval
user.instance_eval {@secret += "1"}

def User.create_test_user
  (u = new).instance_eval do
    @name = "test" 
    @admin = true

# with switch
def User.create_test_user
  new.switch do
    @name = "test" 
    @admin = true
This brings me to my last point. I can’t remember those damn names! And instance_eval is tooo loooong. That’s why I propose these mnemonic names:
  • tap => rsss : Returns Self Same Self
  • with => rrss : Returns Result Same Self
  • instance_eval => rsds : Returns Self Different Self
  • switch => rrds : Returns Result Different Self

Geplaatst in , ,  | geen reacties


(Laat url/e-mail achter »)