Skip to content
This repository
Browse code

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 authored January 16, 2009 lifo committed January 18, 2009
17  activesupport/lib/active_support/core_ext/object/misc.rb
@@ -87,21 +87,4 @@ def acts_like?(duck)
87 87
     respond_to? "acts_like_#{duck}?"
88 88
   end
89 89
 
90  
-  # Tries to send the method only if object responds to it. Return +nil+ otherwise.
91  
-  # It will also forward any arguments and/or block like Object#send does.
92  
-  # 
93  
-  # ==== Example :
94  
-  # 
95  
-  # # Without try
96  
-  # @person ? @person.name : nil
97  
-  # 
98  
-  # With try
99  
-  # @person.try(:name)
100  
-  #
101  
-  # # try also accepts arguments/blocks for the method it is trying
102  
-  # Person.try(:find, 1)
103  
-  # @people.try(:map) {|p| p.name}
104  
-  def try(method, *args, &block)
105  
-    send(method, *args, &block) unless self.nil?
106  
-  end
107 90
 end
30  activesupport/lib/active_support/core_ext/try.rb
... ...
@@ -0,0 +1,30 @@
  1
+class Object
  2
+  # Tries to send the method only if object responds to it. Return +nil+ otherwise.
  3
+  # It will also forward any arguments and/or block like Object#send does.
  4
+  #
  5
+  # ==== Examples
  6
+  #
  7
+  # Without try
  8
+  #   @person && @person.name
  9
+  # or
  10
+  #   @person ? @person.name : nil
  11
+  #
  12
+  # With try
  13
+  #   @person.try(:name)
  14
+  #
  15
+  # Try also accepts arguments/blocks for the method it is trying
  16
+  #   Person.try(:find, 1)
  17
+  #   @people.try(:collect) {|p| p.name}
  18
+  #--
  19
+  # This method def is for rdoc only. The alias_method below overrides it as an optimization.
  20
+  def try(method, *args, &block)
  21
+    send(method, *args, &block)
  22
+  end
  23
+  alias_method :try, :__send__
  24
+end
  25
+
  26
+class NilClass
  27
+  def try(*args)
  28
+    nil
  29
+  end
  30
+end

6 notes 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
Owner

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
Owner

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.