문제

저는 Ruby를 처음 접했기 때문에 제가 겪고 있는 이상한 예외 문제를 이해하는 데 어려움을 겪고 있습니다.Amazon ECS에 액세스하기 위해 ruby-aaws gem을 사용하고 있습니다. http://www.caliban.org/ruby/ruby-aws/.이는 Amazon::AWS:Error 클래스를 정의합니다.

module Amazon
  module AWS
    # All dynamically generated exceptions occur within this namespace.
    #
    module Error
      # An exception generator class.
      #
      class AWSError
        attr_reader :exception

        def initialize(xml)
          err_class = xml.elements['Code'].text.sub( /^AWS.*\./, '' )
          err_msg = xml.elements['Message'].text

          unless Amazon::AWS::Error.const_defined?( err_class )
            Amazon::AWS::Error.const_set( err_class,
                    Class.new( StandardError ) )
          end

          ex_class = Amazon::AWS::Error.const_get( err_class )
          @exception = ex_class.new( err_msg )
        end
      end
    end
  end
end

즉, 다음과 같은 오류 코드가 표시되면 AWS.InvalidParameterValue, 이것은 (예외 변수에서) 새로운 클래스를 생성합니다 Amazon::AWS::Error::InvalidParameterValue 이는 의 하위 클래스입니다. StandardError.

이제 여기서 이상해집니다.다음과 같은 코드가 있습니다.

begin
  do_aws_stuff
rescue Amazon::AWS::Error => error
  puts "Got an AWS error"
end

이제 만약에 do_aws_stuff 던진다 NameError, 내 구조 블록이 실행됩니다.Amazon::AWS::Error는 생성된 오류의 슈퍼클래스가 아닌 것 같습니다. 모듈이므로 모든 것이 그것의 하위 클래스인 것 같습니다.물론 내가 그렇게 한다면:

irb(main):007:0> NameError.new.kind_of?(Amazon::AWS::Error)
=> true

그것은 말한다 true, 특히 다음과 같은 점을 고려하면 혼란스럽습니다.

irb(main):009:0> NameError.new.kind_of?(Amazon::AWS)
=> false

무슨 일이 일어나고 있으며, AWS 오류를 다른 유형의 오류와 어떻게 구분해야 합니까?다음과 같이 해야 할까요?

begin
  do_aws_stuff
rescue => error
  if error.class.to_s =~ /^Amazon::AWS::Error/
    puts "Got an AWS error"
  else
    raise error
  end
end

유난히 버벅거리는 것 같아요.발생한 오류는 AWSError 클래스도 아니며 다음과 같이 발생합니다.

error = Amazon::AWS::Error::AWSError.new( xml )
raise error.exception

그래서 내가 찾고 있는 예외는 rescue from은 StandardError에서만 상속되는 생성된 예외 유형입니다.

명확히하기 위해 두 가지 질문이 있습니다.

  1. Ruby에 내장된 예외인 NameError는 왜 kind_of?(Amazon::AWS::Error), 모듈은 무엇입니까?
    답변: 나는 말했다 include Amazon::AWS::Error 내 파일 상단에 Java 가져오기 또는 C++ 포함과 비슷하다고 생각했습니다.이것이 실제로 한 일은 다음에 정의된 모든 것을 추가한 것입니다. Amazon::AWS::Error (현재 및 미래)를 모든 클래스의 조상인 암시적 커널 클래스에 적용합니다.이는 다음을 의미합니다. 아무것 통과할 것이다 kind_of?(Amazon::AWS::Error).

  2. 동적으로 생성된 예외를 가장 잘 구별할 수 있는 방법은 무엇입니까? Amazon::AWS::Error 다른 곳에서 무작위로 다른 예외가 발생합니까?

도움이 되었습니까?

해결책

좋습니다. 제가 도와드리겠습니다.

먼저 모듈은 클래스가 아닙니다. 모듈을 사용하면 클래스의 동작을 혼합할 수 있습니다.두 번째로 다음 예를 참조하세요.

module A
  module B
    module Error
      def foobar
        puts "foo"
      end
    end
  end
end

class StandardError
  include A::B::Error
end

StandardError.new.kind_of?(A::B::Error)
StandardError.new.kind_of?(A::B)
StandardError.included_modules #=> [A::B::Error,Kernel]

종류?예, Error는 A::B::Error 동작을 모두 포함하지만(A::B::Error를 포함하므로 정상임) A::B의 모든 동작을 포함하지 않으므로 오류가 아닙니다. A::B 종류입니다.(오리 타이핑)

이제 ruby-aws가 NameError의 슈퍼클래스 중 하나를 다시 열고 거기에 Amazon::AWS:Error를 포함할 가능성이 매우 높습니다.(원숭이 패치)

다음을 사용하여 모듈이 계층 구조에 포함된 위치를 프로그래밍 방식으로 확인할 수 있습니다.

class Class
  def has_module?(module_ref)
    if self.included_modules.include?(module_ref) and not self.superclass.included_modules.include?(module_ref)                      
        puts self.name+" has module "+ module_ref.name          
    else
      self.superclass.nil? ? false : self.superclass.has_module?(module_ref)
    end        
  end
end
StandardError.has_module?(A::B::Error)
NameError.has_module?(A::B::Error)

두 번째 질문에 관해서는 그보다 더 나은 것을 볼 수 없습니다

begin 
#do AWS error prone stuff
rescue Exception => e
  if Amazon::AWS::Error.constants.include?(e.class.name)
    #awsError
  else
    whatever
  end 
end

(편집 - 위 코드는 있는 그대로 작동하지 않습니다.이름에는 상수 배열의 경우가 아닌 모듈 접두사가 포함됩니다.lib 관리자에게 문의해야 합니다. AWSError 클래스는 제게는 팩토리 클래스처럼 보입니다. :/)

여기에는 ruby-aws가 없고 caliban 사이트는 회사 방화벽에 의해 차단되어 있어 더 이상 테스트할 수 없습니다.

포함에 관해서 :그것은 StandardError 계층 구조에서 원숭이 패치를 수행하는 것일 수 있습니다.더 이상 확실하지 않지만 모든 컨텍스트 외부의 파일 루트에서 이를 수행하는 것은 Object 또는 Object 메타클래스의 모듈을 포함하는 것입니다.(이것은 기본 컨텍스트가 Object인 IRB에서 발생하는 일이며 파일에서는 확실하지 않습니다.)

~로부터 모듈의 곡괭이 :

A couple of points about the include statement before we go on. First, it has nothing to do with files. C programmers use a preprocessor directive called #include to insert the contents of one file into another during compilation. The Ruby include statement simply makes a reference to a named module. If that module is in a separate file, you must use require to drag that file in before using include.

(편집 -- 이 브라우저를 사용하여 댓글을 달 수 없는 것 같습니다./예, 플랫폼에 잠겨 있어서요)

다른 팁

글쎄요, 제가 알 수 있는 바는 다음과 같습니다.

Class.new( StandardError )

StandardError를 기본 클래스로 사용하여 새 클래스를 생성하므로 Amazon::AWS::Error가 전혀 발생하지 않습니다.그것은 해당 모듈에 정의되어 있는데, 이것이 아마도 kind_of인 이유일까요?아마존::AWS::오류.아마도 일종의 종류가 아닌가?Amazon::AWS 모듈이 kind_of 목적으로 중첩되지 않기 때문일까요??

죄송합니다. 저는 Ruby의 모듈을 잘 모르지만, 가장 확실하게 기본 클래스는 StandardError가 될 것입니다.

업데이트:그런데, 루비 문서에서:

obj.kind_of?(class) => 참 또는 거짓

클래스가 obj의 클래스이거나 클래스가 obj의 슈퍼클래스 중 하나이거나 obj에 포함된 모듈인 경우 true를 반환합니다.

그냥 차임하고 싶었어요:나는 이것이 lib 코드의 버그라는 데 동의합니다.아마 다음과 같이 읽어야 할 것입니다:

      unless Amazon::AWS::Error.const_defined?( err_class )
        kls = Class.new( StandardError )
        Amazon::AWS::Error.const_set(err_class, kls)
        kls.include Amazon::AWS::Error
      end

당신이 겪고 있는 한 가지 문제는 Amazon::AWS::Error::AWSError 사실 예외는 아니다.언제 raise 호출되면 첫 번째 매개변수가 exception 메서드를 사용하고 그 결과를 대신 사용합니다.하위 클래스인 모든 것 Exception 다음과 같은 경우에는 자동으로 반환됩니다. exception 다음과 같은 작업을 수행할 수 있도록 호출됩니다. raise Exception.new("Something is wrong").

이 경우, AWSError 가지다 exception 초기화 시 값을 다음과 같이 정의하는 속성 판독기로 설정합니다. Amazon::AWS::Error::SOME_ERROR.즉, 전화할 때 raise Amazon::AWS::Error::AWSError.new(SOME_XML) 루비가 전화를 걸어요 Amazon::AWS::Error::AWSError.new(SOME_XML).exception 이는 다음의 인스턴스를 반환합니다. Amazon::AWS::Error::SOME_ERROR.다른 응답자 중 한 명이 지적했듯이 이 클래스는 StandardError 일반적인 Amazon 오류의 하위 클래스가 되는 대신.이 문제가 해결될 때까지 Jean의 솔루션이 아마도 최선의 선택일 것입니다.

실제로 뒤에서 무슨 일이 일어나고 있는지 더 자세히 설명하는 데 도움이 되었기를 바랍니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top