Browse files

Allow optional arguments and/or block for Object#try like Object#send…

… does. [#1425 state:resolved]

Original suggestion by Pat Nakajima.

Signed-off-by: Pratik Naik <>
  • Loading branch information...
1 parent fffb1da commit 823b623fe2de8846c37aa13250010809ac940b57 @alloy alloy committed with lifo Nov 21, 2008
@@ -73,6 +73,7 @@ def acts_like?(duck)
# Tries to send the method only if object responds to it. Return +nil+ otherwise.
+ # It will also forward any arguments and/or block like Object#send does.
# ==== Example :
@@ -81,7 +82,11 @@ def acts_like?(duck)
# With try
# @person.try(:name)
- def try(method)
- send(method) if respond_to?(method, true)
+ #
+ # # try also accepts arguments/blocks for the method it is trying
+ # Person.try(:find, 1)
+ # @people.try(:map) {|p|}
+ def try(method, *args, &block)
+ send(method, *args, &block) if respond_to?(method, true)
@@ -271,4 +271,11 @@ class << @string
assert_equal 5, @string.try(:size)
+ def test_argument_forwarding
+ assert_equal 'Hey', @string.try(:sub, 'llo', 'y')
+ end
+ def test_block_forwarding
+ assert_equal 'Hey', @string.try(:sub, 'llo') { |match| 'y' }
+ end

4 comments on commit 823b623

rdp replied Feb 21, 2009

This definition of try would seriously benefit from being implemented like andand, at least from my side of the fence.

bitti replied Mar 3, 2009

rogerdpack is right. The current semantic has many problems.

Firstly the major usecase for try is to catch the case when the receiver is nil, not so much if the method is defined on the receiver. There are also lots of methods on nil, so e.g. object.try(:id) will not archive anything besides subtle errors.

Secondly, because catching the first missing method is not enough, one often sees cascades of two ore more tries:


but (apart from the hard to read syntax) it can hide many problems, because if address is defined one expects to have a reset method on it and otherwise get an exception. So like in andand it would be better to have something like

User.admin.try { |u| u.address.reset }

I guess this form can even be implemented without breaking compatibility with the old form (because the current implementation expects a “method” parameter)

bitti replied Mar 3, 2009

Sorry it should’ve read

User.admins.first.try { |u| u.address.reset }

It seems like the behavior one really wants is
x != nil ? x.send(*args) : nil

which is rather different than the implementation.

Please sign in to comment.