From 79fabe094a39c390205c778d4ccb32c9470c7a1a Mon Sep 17 00:00:00 2001 From: Bryan Larsen Date: Wed, 18 Nov 2009 09:28:22 -0500 Subject: [PATCH] [#537 state:resolved] This changes the behaviour of the `._?.` "dot". It now returns 'nil' rather than calling the trailing function more often. --- hobosupport/lib/hobo_support/methodcall.rb | 27 +++++++++++++++++++++++++-- hobosupport/test/hobosupport.rdoctest | 18 +++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/hobosupport/lib/hobo_support/methodcall.rb b/hobosupport/lib/hobo_support/methodcall.rb index 85b688a..f3028e0 100644 --- a/hobosupport/lib/hobo_support/methodcall.rb +++ b/hobosupport/lib/hobo_support/methodcall.rb @@ -56,9 +56,32 @@ end class SafeNil include Singleton + DONT_REDEFINE_METHODS = "__id__", "__send__" + + NIL_RESPONSE_METHODS = ["to_s", "to_json", "to_yaml", "__id__", "__is_a__", "__metaclass__", "__send__"] + + (NIL_RESPONSE_METHODS - DONT_REDEFINE_METHODS).each do |method| + # can't use define_method with a block + eval " + def #{method}(*args, &b) + nil.send(:#{method}, *args, &b) + end" + end + + (instance_methods - NIL_RESPONSE_METHODS - DONT_REDEFINE_METHODS).each do |method| + # can't use define_method with a block + eval " + def #{method}(*args, &b) + nil + end" + end + + def to_s + "" + end + def method_missing(method, *args, &b) - return nil unless nil.respond_to? method - nil.send(method, *args, &b) rescue nil + return nil end end diff --git a/hobosupport/test/hobosupport.rdoctest b/hobosupport/test/hobosupport.rdoctest index 66b22db..9e0241b 100644 --- a/hobosupport/test/hobosupport.rdoctest +++ b/hobosupport/test/hobosupport.rdoctest @@ -34,15 +34,21 @@ Like `is_a?` but multiple types to be checked in one go ## Method call extensions +We have the "." operator to call methods on objects. These extensions introduce two "special dots". + ### `Object#_?` -We have the "." operator to call methods on objects. These extensions introduce two "special dots". "`._?.`" only calls the method if the receiver is not `nil`. +"`._?.`" only calls the method if the receiver is not `nil`. Otherwise it returns nil. >> "foo"._?.length => 3 >> nil._?.length => nil +`to_s`, `to_yaml` and `to_json` and a few system functions that start with an underscore are the only exceptions -- they call their corresponding functions on nil. + + >> nil._?.to_s + => "" ### `Object#try` @@ -53,4 +59,14 @@ We have the "." operator to call methods on objects. These extensions introduce >> :foo.try.length => nil +### What's the difference? +`_?` is generally used when nil is an expected response. `try` is +generally used when interfaces may be different. For instance, you +may use `try` to call a Rails 2.3 function that doesn't exist on Rails +2.2. nil responds to some functions that may surprise you. + + >> nil.try.to_i + => 0 + >> nil._?.to_i + => nil -- 1.6.3.3