Skip to content
Browse files

Refactor Object#try to use inheritance. [#1774 state:resolved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
  • Loading branch information...
1 parent 3b1cd9e commit 78f2c19ae7f9236591c261eecdf0c4b570e3ea1e @joshsusser joshsusser committed with lifo Jan 16, 2009
View
17 activesupport/lib/active_support/core_ext/object/misc.rb
@@ -87,21 +87,4 @@ def acts_like?(duck)
respond_to? "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 :
- #
- # # Without try
- # @person ? @person.name : nil
- #
- # With try
- # @person.try(:name)
- #
- # # 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) unless self.nil?
- end
end
View
30 activesupport/lib/active_support/core_ext/try.rb
@@ -0,0 +1,30 @@
+class Object
+ # 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.
+ #
+ # ==== Examples
+ #
+ # Without try
+ # @person && @person.name
+ # or
+ # @person ? @person.name : nil
+ #
+ # With try
+ # @person.try(:name)
+ #
+ # Try also accepts arguments/blocks for the method it is trying
+ # Person.try(:find, 1)
+ # @people.try(:collect) {|p| p.name}
+ #--
+ # This method def is for rdoc only. The alias_method below overrides it as an optimization.
+ def try(method, *args, &block)
+ send(method, *args, &block)
+ end
+ alias_method :try, :__send__
+end
+
+class NilClass
+ def try(*args)
+ nil
+ end
+end

6 comments on commit 78f2c19

@christos

Isn’t the method name and the documentation a bit misleading?

Tries to send the method only if object responds to it. Return nil otherwise.

It would seem that it only works if the object is nil OR responds to the method.

>> @person = "Bob"
>> @person.try(:name) # would have expected nil as object dosen't respond to name
NoMethodError: undefined method `name' for "Bob":String

My understanding of it is that it should replace this idiomatic Ruby:

@person && @person.name || 'No name'

with this

@person.try(:name) || 'No name'
 

…as first described here: http://ozmm.org/posts/try.html

@dstrelau

christos: that's how @#try used to behave. See this commit and this post for the background.

@christos

Fair enough. The docs are still not clear though:

Tries to send the method only if object responds to it. Return nil otherwise.

If the method doesn’t respond to the method, it raises NoMethodError

Shouldn’t that be documented?

@lifo
Ruby on Rails member
lifo commented on 78f2c19 Jan 24, 2009

Christos : Yeah looks like the doc need fixing. I’ve added you to docrails. So maybe you can make that happen :) Just push the doc fix to the docrails branch and it’ll be merged with the rails/master soon.

@christos

Pratik: Fixed at http://github.com/lifo/docrails/commit/929088189de1d189c643246a491ba8fb5347b1d3

@lifo
Ruby on Rails member
lifo commented on 78f2c19 Jan 26, 2009

Hey Chris,

Thanks. I had reverted that commit and applied it with some changes.

Please sign in to comment.
Something went wrong with that request. Please try again.