Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
  • Loading branch information...
commit 78f2c19ae7f9236591c261eecdf0c4b570e3ea1e 1 parent 3b1cd9e
@joshsusser joshsusser authored lifo committed
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
Collaborator

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
Collaborator

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.