public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Added Object#try. ( Taken from http://ozmm.org/posts/try.html ) [Chris 
Wanstrath]
lifo (author)
Wed Nov 19 06:06:42 -0800 2008
commit  51730792ca930a896361eb92354a42bc56903de1
tree    da1992628081de9c2c0f09b64e1d55893d6e2bcd
parent  51a19ae2bf33e66b23ff5c91bf584b2efa9e669f
...
1
2
 
 
3
4
5
...
1
2
3
4
5
6
7
0
@@ -1,5 +1,7 @@
0
 *2.3.0 [Edge]*
0
 
0
+* Added Object#try. ( Taken from http://ozmm.org/posts/try.html ) [Chris Wanstrath]
0
+
0
 * Added Enumerable#none? to check that none of the elements match the block #1408 [Damian Janowski]
0
 
0
 * TimeZone offset tests: use current_period, to ensure TimeZone#utc_offset is up-to-date [Geoff Buesing]
...
71
72
73
 
 
 
 
 
 
 
 
 
 
 
 
 
74
...
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
0
@@ -71,4 +71,17 @@ class Object
0
   def acts_like?(duck)
0
     respond_to? "acts_like_#{duck}?"
0
   end
0
+
0
+  # Tries to send the method only if object responds to it. Return +nil+ otherwise.
0
+  # 
0
+  # ==== Example :
0
+  # 
0
+  # # Without try
0
+  # @person ? @person.name : nil
0
+  # 
0
+  # With try
0
+  # @person.try(:name)
0
+  def try(method)
1
+    send(method) if respond_to?(method, true)
0
+  end
0
 end
...
247
248
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
0
@@ -247,3 +247,28 @@ class ObjectInstanceVariableTest < Test::Unit::TestCase
0
       [arg] + instance_exec('bar') { |v| [reverse, v] } }
0
   end
0
 end
0
+
0
+class ObjectTryTest < Test::Unit::TestCase
0
+  def setup
0
+    @string = "Hello"
0
+  end
0
+
0
+  def test_nonexisting_method
0
+    method = :undefined_method
0
+    assert !@string.respond_to?(method)
0
+    assert_nil @string.try(method)
0
+  end
0
+  
0
+  def test_valid_method
0
+    assert_equal 5, @string.try(:size)
0
+  end
0
+
0
+  def test_valid_private_method
0
+    class << @string
0
+      private :size
0
+    end
0
+
0
+    assert_equal 5, @string.try(:size)
0
+  end
0
+
0
+end

Comments

fxn Wed Nov 19 06:18:02 -0800 2008

I like the functionality, but the name doesn’t quite “click” to me either.

Bang methods have different semantics… what about “send?”. Oh, the signature could accept args as well.

alloy Wed Nov 19 06:56:04 -0800 2008

Nice!

simonmenke Wed Nov 19 07:05:35 -0800 2008

‘send?’ would be nice.

rogerdpack Wed Nov 19 07:25:28 -0800 2008

take a look at .andand http://weblog.raganwald.com/2008/01/objectandand-objectme-in-ruby.html though renaming it ._? might be nicer # almost equivalent to groovy’s object.?.method

Roman2K Wed Nov 19 12:28:35 -0800 2008

+1 for send?

Aupajo Wed Nov 19 13:05:27 -0800 2008

How about `attempt?`? Try reminds me of `try… catch`

`person.attempt?(:name)`

henrik Wed Nov 19 13:40:08 -0800 2008

+1 for “send?”.

nakajima Wed Nov 19 13:56:40 -0800 2008

I like the name try, though I prefer a version that allows arguments and/or a block: http://gist.github.com/26751

alloy Wed Nov 19 14:15:14 -0800 2008

Try is fine by me, but +1 for nakajima’s patch.

matthewrudy Wed Nov 19 16:42:49 -0800 2008

I particularly like the use of the symbol :wee in his examples.

niessner Wed Nov 19 19:52:42 -0800 2008

why not use a proxy so you could just do string.try.size ?

josegit Wed Nov 19 22:34:26 -0800 2008

-5 for send?. Foo? methods, by convention, return boolean values. Try does not.

nertzy Thu Nov 20 00:02:16 -0800 2008

+1 nakajima

henrik Thu Nov 20 02:05:19 -0800 2008

josegit: That’s usually the case, but not always. To quote matz from a recent ruby-talk thread:

By convention, they are predicates, which means the return value can be considered as boolean value. But at the same time, the values are not limited to true and false. For example, defined? returns the string to describe the kind of expression defined, and nil otherwise.

There’s another convention that when a predicate returns non-true value for represent true, it should return nil for false.

Then again, whether this is a predicate can be discussed. I think I’ll retract my +1 for a ±0.

henrik Thu Nov 20 02:06:36 -0800 2008

Mangled by textile. First and last paragraphs are mine, middle two are quoted from matz.

henrik Thu Nov 20 02:11:53 -0800 2008

A better example may be Ruby’s Numeric#nonzero? which returns the number if it’s not zero and returns nil otherwise. send? would be pretty analogous.

rxcfc Thu Nov 20 06:01:09 -0800 2008

I’ll let others hash out the appropriate method name, but I agree that it should at least support arguments like #send.

lifo Thu Nov 20 06:20:01 -0800 2008

Please submit patches at Lighthouse and assign to me.

Thanks!

adkron Thu Nov 20 08:13:45 -0800 2008

this is nice sugar.

lucianopanaro Fri Nov 21 06:42:54 -0800 2008

Submitted a patch based on alloy’s, adding the option of doing person.try_name(arg1, arg2, ...) { ... }

http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1425-allow-optional-arguments-andor-block-for-objecttry

peanut Fri Nov 21 09:30:31 -0800 2008

Thank you very-very much. I think it will be very useful!

rob-at-thewebfellas Sat Nov 22 02:50:31 -0800 2008

Surely with nakajima’s version it should be called do_or_do_not – remember “there is no try”...

vitaly Tue Nov 25 05:35:56 -0800 2008

The problem is nil.respond_to?(:id) is true. and so you can’t use it as for @object.try.id

nakajima Tue Nov 25 06:13:22 -0800 2008

vitaly: That’s an instance in which you’d probably want to rethink using #try anyway, and instead perhaps structure your interface in such a way that doesn’t return nil objects.

I know it’s ridiculous for me to say this, since I was the one who recommended an “improved” version, but I actually think that nine times out of ten, using #try is a code smell.

noticed a problem.

“some string”.try(:gsub, “some”, “this”) => “this string”

nil.try(:gsub, “some”, “this”) => TypeError: $_ value need to be String (nil given) from (irb):18:in `gsub’ from (irb):18:in `send’ from (irb):18 from :0

This is because nil defines a private method “gsub”. Is there really a need for “try” to “try” private methods? It seems like a less useful case than someone using gsub against an accidental nil.

carlosbrando Fri Jan 09 12:19:29 -0800 2009

+1 nakajima

josevalim Fri Jan 09 17:21:22 -0800 2009