Skip to content

Commit

Permalink
Ensure to return the right offending object if a missing method is ca…
Browse files Browse the repository at this point in the history
…lled with Utils::String and Hash
  • Loading branch information
jodosha committed Jan 2, 2015
1 parent d580069 commit eb097a1
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 12 deletions.
14 changes: 9 additions & 5 deletions lib/lotus/utils/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,16 @@ def inspect
#
# @api private
# @since 0.3.0
#
# @raise [NoMethodError] If doesn't respond to the given method
def method_missing(m, *args, &blk)
h = @hash.__send__(m, *args, &blk)
h = self.class.new(h) if h.is_a?(::Hash)
h
rescue NoMethodError
raise NoMethodError.new(%(undefined method `#{ m }' for #{ @hash }:#{ self.class }))
if respond_to?(m)
h = @hash.__send__(m, *args, &blk)
h = self.class.new(h) if h.is_a?(::Hash)
h
else
raise NoMethodError.new(%(undefined method `#{ m }' for #{ @hash }:#{ self.class }))
end
end

# Override Ruby's respond_to_missing? in order to support ::Hash interface
Expand Down
22 changes: 15 additions & 7 deletions lib/lotus/utils/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,20 +207,28 @@ def split(pattern, limit = 0)
# @see http://www.ruby-doc.org/core/String.html#method-i-gsub
#
# @since 0.3.0
def gsub(pattern, replacement, &blk)
@string.gsub(pattern, replacement, &blk)
def gsub(pattern, replacement = nil, &blk)
if block_given?
@string.gsub(pattern, &blk)
else
@string.gsub(pattern, replacement)
end
end

# Override Ruby's method_missing in order to provide ::String interface
#
# @api private
# @since 0.3.0
#
# @raise [NoMethodError] If doesn't respond to the given method
def method_missing(m, *args, &blk)
s = @string.__send__(m, *args, &blk)
s = self.class.new(s) if s.is_a?(::String)
s
rescue NoMethodError
raise NoMethodError.new(%(undefined method `#{ m }' for "#{ @string }":#{ self.class }))
if respond_to?(m)
s = @string.__send__(m, *args, &blk)
s = self.class.new(s) if s.is_a?(::String)
s
else
raise NoMethodError.new(%(undefined method `#{ m }' for "#{ @string }":#{ self.class }))
end
end

# Override Ruby's respond_to_missing? in order to support ::String interface
Expand Down
13 changes: 13 additions & 0 deletions test/hash_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,19 @@
e.message.must_equal %(undefined method `party!' for {\"l\"=>23}:Lotus::Utils::Hash)
end
end

# See: https://github.com/lotus/utils/issues/48
it 'returns the correct object when a NoMethodError is raised' do
hash = Lotus::Utils::Hash.new({'a' => 1})
exception_message = if Lotus::Utils.rubinius?
"undefined method `foo' on 1:Fixnum."
else
"undefined method `foo' for 1:Fixnum"
end

exception = -> { hash.all? {|_, v| v.foo } }.must_raise NoMethodError
exception.message.must_equal exception_message
end
end
end
end
13 changes: 13 additions & 0 deletions test/string_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -206,5 +206,18 @@
e.message.must_equal %(undefined method `yay!' for "one":Lotus::Utils::String)
end
end

# See: https://github.com/lotus/utils/issues/48
it 'returns the correct object when a NoMethodError is raised' do
string = Lotus::Utils::String.new('/path/to/something')
exception_message = if Lotus::Utils.rubinius?
%(undefined method `boom' on an instance of String.)
else # MRI
%(undefined method `boom' for "/":String)
end

exception = -> { string.gsub(/\//) {|s| s.boom }}.must_raise NoMethodError
exception.message.must_equal exception_message
end
end
end

0 comments on commit eb097a1

Please sign in to comment.