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
Josh Susser joshsusser authored lifo committed
17 activesupport/lib/active_support/core_ext/object/misc.rb
View
@@ -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
30 activesupport/lib/active_support/core_ext/try.rb
View
@@ -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 Zisopoulos

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

Dean Strelau

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

Christos Zisopoulos

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?

Pratik
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 Zisopoulos

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

Pratik
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.