Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
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 <pratiknaik@gmail.com>
  • Loading branch information...
commit 823b623fe2de8846c37aa13250010809ac940b57 1 parent fffb1da
@alloy alloy authored lifo committed
View
9 activesupport/lib/active_support/core_ext/object/misc.rb
@@ -73,6 +73,7 @@ def acts_like?(duck)
end
# 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| p.name}
+ def try(method, *args, &block)
+ send(method, *args, &block) if respond_to?(method, true)
end
end
View
7 activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -271,4 +271,11 @@ class << @string
assert_equal 5, @string.try(:size)
end
+ 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
end

4 comments on commit 823b623

@rdp

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

@bitti

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:

User.admins.first.try(:address).try(:reset)

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

Sorry it should’ve read

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

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.
Something went wrong with that request. Please try again.