From c8f7e94eec25dbc981af77bbb5e462867c402d07 Mon Sep 17 00:00:00 2001 From: Amos King Date: Tue, 29 Jun 2010 23:42:05 -0500 Subject: [PATCH] adds support for try as a proxy object [#5013 state:resolved] --- .../lib/active_support/core_ext/object/try.rb | 31 ++++++---------- .../test/core_ext/object_and_class_ext_test.rb | 36 +++++++++++++++++--- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb index a1c63a0..f574195 100644 --- a/activesupport/lib/active_support/core_ext/object/try.rb +++ b/activesupport/lib/active_support/core_ext/object/try.rb @@ -1,9 +1,6 @@ class Object - # Invokes the method identified by the symbol +method+, passing it any arguments - # and/or the block specified, just like the regular Ruby Object#send does. - # - # *Unlike* that method however, a +NoMethodError+ exception will *not* be raised - # and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass. + # 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 # @@ -13,24 +10,20 @@ class Object # @person ? @person.name : nil # # With try - # @person.try(:name) + # @person.try.name # - # +try+ also accepts arguments and/or a block, for the method it is trying - # Person.try(:find, 1) - # @people.try(:collect) {|p| p.name} - #-- - # This method definition below is for rdoc purposes only. The alias_method call - # below overrides it as an optimization since +try+ behaves like +Object#send+, - # unless called on +NilClass+. - def try(method, *args, &block) - send(method, *args, &block) + # Try also accepts arguments/blocks for the method it is trying + # Person.try.find(1) + # @people.try.collect {|p| p.name} + def try(method = nil, *args, &block) + method ? self.send(method, *args, &block) : self end - remove_method :try - alias_method :try, :__send__ end -class NilClass #:nodoc: +class NilClass + Try = Class.new(BlankSlate) { def method_missing(*) nil; end } + def try(*args) - nil + args.empty? ? Try.new : nil end end diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb index 5e03389..3a90b07 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -189,29 +189,55 @@ class ObjectTryTest < Test::Unit::TestCase end def test_nonexisting_method + assert !@string.respond_to?(:undefined_method) + assert_raise(NoMethodError) { @string.try.undefined_method } + end + + def test_valid_method + assert_equal 5, @string.try.size + end + + def test_argument_forwarding + assert_equal 'Hey', @string.try.sub('llo', 'y') + end + + def test_block_forwarding + assert_equal 'Hey', @string.try.sub('llo') { |match| 'y' } + end + + def test_nil_to_type + assert_nil nil.try.to_s + assert_nil nil.try.to_i + end + + def test_false_try + assert_equal 'false', false.try.to_s + end + + def test_nonexisting_method_depricated method = :undefined_method assert !@string.respond_to?(method) assert_raise(NoMethodError) { @string.try(method) } end - def test_valid_method + def test_valid_method_depricated assert_equal 5, @string.try(:size) end - def test_argument_forwarding + def test_argument_forwarding_depricated assert_equal 'Hey', @string.try(:sub, 'llo', 'y') end - def test_block_forwarding + def test_block_forwarding_depricated assert_equal 'Hey', @string.try(:sub, 'llo') { |match| 'y' } end - def test_nil_to_type + def test_nil_to_type_depricated assert_nil nil.try(:to_s) assert_nil nil.try(:to_i) end - def test_false_try + def test_false_try_depricated assert_equal 'false', false.try(:to_s) end end -- 1.6.2.1.389.geed1