DidYouMean 모듈
DidYouMean 모듈
NameError나 NoMethodError를 만나면 Ruby가 "혹시 이거 말고 이거였어요?" 하고 후보를 제시해 주는 경우가 많죠. 그 기능을 담당하는 게 DidYouMean 젬이에요. 메서드명이나 클래스명이 틀렸을 때 그럴듯한 대안 이름을 제안해 줘요. Ruby 2.3 이후로는 시작할 때 자동으로 활성화돼요.
어떤 오류를 잡아 주나요
오타 하나가 어떤 오류를 만드는지 직접 보는 게 가장 빠른데요, 아래 예시들이 전형적인 모습이에요.
methosd
# => NameError: undefined local variable or method `methosd' for main:Object
# Did you mean? methods
# method
OBject
# => NameError: uninitialized constant OBject
# Did you mean? Object
@full_name = "Yuki Nishijima"
first_name, last_name = full_name.split(" ")
# => NameError: undefined local variable or method `full_name' for main:Object
# Did you mean? @full_name
@@full_name = "Yuki Nishijima"
@@full_anme
# => NameError: uninitialized class variable @@full_anme in Object
# Did you mean? @@full_name
full_name = "Yuki Nishijima"
full_name.starts_with?("Y")
# => NoMethodError: undefined method `starts_with?' for "Yuki Nishijima":String
# Did you mean? start_with?
hash = {foo: 1, bar: 2, baz: 3}
hash.fetch(:fooo)
# => KeyError: key not found: :fooo
# Did you mean? :foo
did_you_mean 끄기
가끔은 오류 객체 자체의 문제를 디버깅할 때처럼 이 제안 기능을 끄고 싶을 때가 있어요. ruby 명령에 --disable-did_you_mean 옵션을 주면 완전히 끌 수 있어요:
$ ruby --disable-did_you_mean -e "1.zeor?"
-e:1:in `<main>': undefined method `zeor?' for 1:Integer (NameError)
ruby 명령에 직접 접근할 수 없는 경우(예: rails console, irb)에는 RUBYOPT 환경 변수로 옵션을 적용할 수 있어요:
$ RUBYOPT='--disable-did_you_mean' irb
irb:0> 1.zeor?
# => NoMethodError (undefined method `zeor?' for 1:Integer)
원래 오류 메시지 가져오기
때로는 젬을 통째로 끄기보다, 제안 없이 원래 오류 메시지만 얻고 싶을 때가 있어요(예: 테스트). 이럴 땐 오류 객체의 original_message 메서드를 쓰면 돼요:
no_method_error = begin
1.zeor?
rescue NoMethodError => error
error
end
no_method_error.message
# => NoMethodError (undefined method `zeor?' for 1:Integer)
# Did you mean? zero?
no_method_error.original_message
# => NoMethodError (undefined method `zeor?' for 1:Integer)
보시다시피 message에는 제안이 붙지만, original_message은 순수한 원래 메시지만 돌려줘요.
상수
PlainFormatter—DidYouMean::Formatter는 이 젬의 기본 포맷터예요.message_for메서드에 응답하며 사람이 읽을 수 있는 문자열을 돌려줘요.VERSION— 버전 문자열VerboseFormatter—PlainFormatter보다 더 상세한 제안을 만들어 주는 포맷터예요.
클래스 메서드
-
correct_error(error_class, spell_checker)— 주어진 spell checker로 오류에DidYouMean기능을 더해줘요.# File lib/did_you_mean.rb, line 97 def self.correct_error(error_class, spell_checker) if defined?(Ractor) new_mapping = { **@spell_checkers, error_class.to_s => spell_checker } new_mapping.default = NullChecker @spell_checkers = Ractor.make_shareable(new_mapping) else spell_checkers[error_class.to_s] = spell_checker end error_class.prepend(Correctable) if error_class.is_a?(Class) && !(error_class < Correctable) end -
formatter()— 현재 설정된 포맷터를 돌려줘요. 기본값은DidYouMean::Formatter예요.# File lib/did_you_mean.rb, line 117 def self.formatter if defined?(Ractor) Ractor.current[:__did_you_mean_formatter__] || Formatter else Formatter end end -
formatter=(formatter)— 제안을 포맷할 때 쓰이는 기본 포맷터를 갱신해요.# File lib/did_you_mean.rb, line 126 def self.formatter=(formatter) if defined?(Ractor) Ractor.current[:__did_you_mean_formatter__] = formatter end end -
spell_checkers()— 오류 타입과 spell checker 객체의 공유 가능한 해시 맵을 돌려줘요.# File lib/did_you_mean.rb, line 92 def self.spell_checkers @spell_checkers end