Skip to content

Commit

Permalink
[#537 state:resolved]
Browse files Browse the repository at this point in the history
This changes the behaviour of the `._?.` "dot".  It now returns 'nil'
rather than calling the trailing function more often.
  • Loading branch information
bryanlarsen committed Nov 18, 2009
1 parent f46f683 commit a13c220
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 3 deletions.
15 changes: 15 additions & 0 deletions hobo/CHANGES.txt
Expand Up @@ -10,6 +10,21 @@ likely to cause conflicts, so it is highly recommended that you have
your code backed up and in a change control system such as git or
subversion.

=== Hobo Edge ===

Major enhancements:

Major bug fixes:

- [#537](https://hobo.lighthouseapp.com/projects/8324-hobo/tickets/537)
The `._?.` "smart dot" now returns 'nil' rather than calling its
trailing function more often than it used to, more closely
matching its documentation.

Minor enhancements:

Minor bug fixes:

=== Hobo 0.9.0 ===

Major enhancements:
Expand Down
27 changes: 25 additions & 2 deletions hobosupport/lib/hobo_support/methodcall.rb
Expand Up @@ -56,9 +56,32 @@ def try(*args)
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

Expand Down
18 changes: 17 additions & 1 deletion hobosupport/test/hobosupport.rdoctest
Expand Up @@ -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`

Expand All @@ -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

0 comments on commit a13c220

Please sign in to comment.