$ ) " / * 4 . w 1JDLTVQUIFNPTUMJLFMZTQFMMJOHDPSSFDUJPO T GPSUIFJOQVU w "TQFMMDIFDLFSNBZIBWFTFWFSBMDPOUSPMNFDIBOJTNT w 6TFTPOFPSNPSFNFUSJDT w TJNJMBSJUZCFUXFFOTUSJOHT FH-FWFOTIUFJO +BSP8JOLMFS w OHSBN w /BJWFMZTDBOOJOHBMMUIFXPSETJOUIFEJDUJPOBSZXPVMECF QBJOGVMMZTMPX
u _ m e a n H F N w %JDUJPOBSZ w "TFUPGTZNCPMT w $POUSPMNFDIBOJTN w 6TFT-FWFOTIUFJOEJTUBODFUPDPSSFDUNJTUZQFEXPSET w 6TFT+BSP8JOLMFSEJTUBODFUPDPSSFDUNJTTQFMUXPSET w 0QUJNJ[BUJPO w $POUFYUCBTFEEJDUJPOBSZ
5IFDPSSFDUTQFMMJOHJTNJTSFNFNCFSFEPSOPUSFNFNCFSFEBUBMM w 5IFpSTUDIBSBDUFSJTBMXBZTDPSSFDU • Yannakoudakis, E.J. and Fawthrop, D., "The rules of spelling errors," Information Processing and Management, vol. 19, no. 2, pp. 87-99, 1983. w DPSSFDUFECZUIFdid_you_mean HFNVTJOH+BSP8JOLMFSEJTUBODF
* / * 5 * " - * ; & 3 module DidYouMean class ANameChecker include SpellCheckable def initialize(exception) # pull out the user input and generate # a dictionary using the exception object. end end end
:doesnt_exist end begin DoesntExist rescue NameError => error error.name # => :DoesntExist end begin @@doesnt_exist rescue NameError => error error.name # => :@@doesnt_exist end
& 4 module DidYouMean class MethodNameChecker include SpellCheckable def initialize(no_method_error) # user input @name = no_method_error.name # dictionary @method_names = no_method_error.receiver.methods end end end
NameError => error error.receiver == string # => true end w 6TFEUPCFJNQMFNFOUFEBTB$FYUFOTJPO w *TOPXQBSUPG3VCZ w 3FUVSOTUIFSFDFJWFSXIFSFUIFNFUIPEJTDBMMFEPO
& 4 module DidYouMean class MethodNameChecker include SpellCheckable def initialize(no_method_error) # user input @name = no_method_error.name # dictionary @method_names = no_method_error.receiver.methods end end end
& 4 module DidYouMean class MethodNameChecker include SpellCheckable def initialize(no_method_error) # user input @name = no_method_error.name # dictionary @method_names = no_method_error.receiver.methods end def candidates { @name => @method_names } end end end
4 module DidYouMean class ClassNameChecker include SpellCheckable def initialize(exception) @class_name, @receiver = exception.name, exception.receiver end def candidates { @class_name => class_names } end # generates a dictionary def class_names scopes.flat_map do |scope| scope.constants.map do |constant| scope == Object ? constant : "#{scope}::#{constant}" end end end def scopes @receiver.to_s.split("::").inject([Object]) do |_scopes, scope| _scopes << _scopes.last.const_get(scope) end.uniq end end end
= exception.name, exception.receiver end def candidates { @class_name => class_names } end # generates a dictionary def class_names scopes.flat_map do |scope| scope.constants.map do |constant| scope == Object ? constant : "#{scope}::#{constant}" end end end def scopes @receiver.to_s.split("::").inject([Object]) do |_scopes, scope| _scopes << _scopes.last.const_get(scope) end.uniq end end end $ - " 4 4 / " . & 4 5-%3
4 ... class Person ... def address Address.new(raw_address) end class Address ... def zipcode ZipCode.new(raw_zipcode) # => NameError end class Zipcode ... end end end
4 ... class Person ... def address Address.new(raw_address) end class Address ... def zipcode ZipCode.new(raw_zipcode) # => NameError end class Zipcode ... end end end Object.constants Person.constants Address.constants
4 ... class Person ... def address Address.new(raw_address) end class Address ... def zipcode ZipCode.new(raw_zipcode) # => NameError end class Zipcode ... end end end + + Object.constants Person.constants Address.constants