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:- Are defined for any
Object
- Take a block and always execute it once
- 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.- What do we return? The object itself? Or the result of the block?
- 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)?
tap
: returns result, same self in blockwith
: return self, same self in blockinstance_eval
: returns result, different self in block.
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
b.baz.goo
# 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
end
u
end
# with switch
def User.create_test_user
new.switch do
@name = "test"
@admin = true
end
end
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 Selfwith => rrss
: Returns Result Same Selfinstance_eval => rsds
: Returns Self Different Selfswitch => rrds
: Returns Result Different Self