if no message is set). http://ruby-doc.org/core-2.2.1/Exception.html#method-i-to_s Exception#message Returns the result of invoking exception.to_s. Normally this returns the exception’s message or name. http://ruby-doc.org/core-2.2.1/Exception.html#method-i-message
local variable or method `boom' for main:Object puts error.message # => undefined local variable or method `boom' for main:Object Isn’t that the receiver object?
headers required, head to maintain • Doesn’t compile on all Windows machines • Sometimes doesn’t compile even on OS X • Breaks the default behaviour of NoMethodError#args • Breaks other behaviours of Ruby 2.1.x on OS X, other gems (e.g. letter_opener, arel) have been affected
Rake::ExtensionTask.new('did_you_mean') do |ext| ext.name = "method_receiver" ext.lib_dir = "lib/did_you_mean" end # From terminal $ rake compile require ‘did_you_mean/method_receiver’ # => actives the C extension
to_s msg << super msg << "\n\n" msg << " Did you mean? ##{suggestions.join(', #')}\n" rescue super end def suggestions receiver.methods.select do |name| DidYouMean::Levenshtein.distance(name, self.name) < THRESHOLD end end end "Yuki".starts_with?("Y") # => NoMethodError: undefined method `starts_with?' for "Yuki":String # # Did you mean? #start_with?
suggestions = (local_variables + methods + private_methods).select do |name| Levenshtein.distance(name, error.name) < 2 end end puts suggestions # => [:user] This is the only difference. We can re-use most of the code from NoMethodError
<< super msg << "\n\n" msg << " Did you mean? ##{suggestions.join(', #')}\n" rescue super end def suggestions names.select do |name| DidYouMean::Levenshtein.distance(name, self.name) < THRESHOLD end end def names local_variables + methods + private_methods end end
<< super msg << "\n\n" msg << " Did you mean? ##{suggestions.join(', #')}\n" rescue super end def suggestions names.select do |name| DidYouMean::Levenshtein.distance(name, self.name) < THRESHOLD end end def names local_variables + methods + private_methods end end Same as NoMethodError
<< super msg << "\n\n" msg << " Did you mean? ##{suggestions.join(', #')}\n" rescue super end def suggestions names.select do |name| DidYouMean::Levenshtein.distance(name, self.name) < THRESHOLD end end def names local_variables + methods + private_methods end end
<< super msg << "\n\n" msg << " Did you mean? ##{suggestions.join(', #')}\n" rescue super end def suggestions names.select do |name| DidYouMean::Levenshtein.distance(name, self.name) < THRESHOLD end end def names local_variables + methods + private_methods end end They don’t return what is expected because the scope is different.
end begin create_user rescue NameError => error suggestions = ??????.select do |name| Levenshtein.distance(name, error.name) < 2 end end puts suggestions # => [:user]
end begin create_user rescue NameError => error suggestions = ??????.select do |name| Levenshtein.distance(name, error.name) < 2 end end puts suggestions # => [:user] 1st scope
whenever an exception is raised • Provides access to both the exception object, and the binding from which it was raised • Works on MRI 1.9.3 - 2.2.1, JRuby, and Rubinius
end class NameError THRESHOLD = 2 def to_s msg << super msg << "\n\n" msg << " Did you mean? #{suggestions.join(', ')}\n" rescue super end def suggestions names.select do |name| DidYouMean::Levenshtein.distance(name, self.name) < THRESHOLD end end def names @frame_binding.eval("local_variables + methods + private_methods") end end
constant USer # # Did you mean? User # User.new(nmee: "wrong flrst name") # => ActiveRecord::UnknownAttributeError: unknown attribute: nmee # # Did you mean? name: string #