Frage

Ich bin neu in Ruby, also, ich habe einige Schwierigkeiten zu verstehen, diese seltsame Ausnahme problem, das ich habe.Ich bin mit dem ruby-aaws Juwel, um Zugriff auf Amazon ECS: http://www.caliban.org/ruby/ruby-aws/.Dies definiert eine Klasse von Amazon::AWS:Fehler:

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

Dies bedeutet, dass, wenn Sie einen Fehlercode wie AWS.InvalidParameterValue, daraus wird sich (in seiner Ausnahme-variable) eine neue Klasse Amazon::AWS::Error::InvalidParameterValue was ist eine Unterklasse von StandardError.

Nun, hier wird es komisch.Ich habe einige code, der wie folgt aussieht:

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

Nun, wenn do_aws_stuff wirft ein NameError, meine rescue-block wird ausgelöst.Es scheint, dass Amazon::AWS::Fehler ist nicht die Oberklasse des generierten Fehler, - ich denke, da es ein Modul alles, was eine Unterklasse von es?Sicherlich, wenn ich tun:

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

Es sagt true, finde ich verwirrend, zumal diese:

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

Was ist Los, und wie soll ich den separaten AWS-Fehler aus andere Art von Fehler?Sollte ich etwas tun wie:

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

Das scheint außergewöhnlich kitschige.Die Fehler, die ausgelöst werden, sind nicht Klasse AWSError entweder sind Sie aufgewachsen, wie diese:

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

Also die Ausnahmen, ich bin auf der Suche, um rescue sind die generierten exception-Typen, die nur Erben von StandardError.

Um zu klären, ich habe zwei Fragen:

  1. Warum ist NameError, ein Ruby-Baujahr Ausnahme kind_of?(Amazon::AWS::Error), was ist ein Modul?
    Antwort: Ich hatte gesagt include Amazon::AWS::Error an der Spitze meiner Datei, dachte, es war wie eine Art von import Java oder C++ gehören.Was ist das eigentlich Tat, war fügen Sie alles, was definiert Amazon::AWS::Error (Gegenwart und Zukunft) auf die implizite Kernel-Klasse ist ein Vorfahr von jeder Klasse.Dies bedeutet, dass alles pass kind_of?(Amazon::AWS::Error).

  2. Wie kann ich am besten unterscheiden, die dynamisch erstellten Ausnahmen Amazon::AWS::Error aus zufälligen andere Ausnahmen von anderswo?

War es hilfreich?

Lösung

Ok, ich werde versuchen, hier zu helfen :

Zuerst ein Modul ist keine Klasse, es ermöglicht Sie zu mischen Verhalten in einer Klasse.zweite siehe das folgende Beispiel :

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]

kind_of?sagt Sie ja, Fehler macht besitzen Alle von A::B::Error Verhalten (das ist normal, denn es enthält A::B::Error) jedoch nicht alle das Verhalten von A::B und ist daher nicht der A::B Art.(duck typing)

Jetzt gibt es eine sehr gute chance, dass ruby-aws-öffnet eine der Oberklasse NameError und enthält Amazon::AWS:Fehler drin.(monkey-patching)

Finden Sie ein Programm, in dem das Modul enthalten ist, in der Hierarchie mit den folgenden :

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)

Bezüglich deiner zweiten Frage kann ich nicht sehen, nichts besser als

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

(Bearbeiten -- obigen code nicht funktioniert ist :name enthält-Modul-Präfix, das ist nicht der Fall, der die Konstanten-arrays.Sie sollten auf jeden Fall Kontakt mit der lib Betreuer der AWSError Klasse sieht eher aus wie eine factory-Klasse zu mir :/ )

Ich habe keine ruby-aws-hier caliban und die Seite ist blockiert durch firewall des Unternehmens, so kann ich nicht testen, viel weiter.

In Bezug auf die enthalten :das könnte der Sache zu tun die monkey-patching auf der Standardfehler Hierarchie.Ich bin mir nicht mehr sicher, aber wahrscheinlich tun Sie es im Stammverzeichnis eine Datei außerhalb jeder Kontext ist darunter das Modul auf einem Objekt oder über das Objekt metaclass.(dies ist, was passieren würde, in IRB, wo die Standard-Kontext-Objekt, nicht sicher in einer Datei)

aus der Spitzhacke auf Module :

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.

(Bearbeiten -- ich kann nicht scheinen, um einen Kommentar abgeben zu können mit dieser browser -: / yay für locked-in-Plattformen)

Andere Tipps

Naja, was ich sagen kann:

Class.new( StandardError )

Ist die Schaffung einer neuen Klasse mit Standardfehler als Basisklasse, so ist es nicht zu Amazon::AWS::Fehler überhaupt.Es ist nur definiert, das Modul, die ist wahrscheinlich, warum es ist ein kind_of?Amazon::AWS::Error.Es ist wahrscheinlich nicht eine kind_of?Amazon::AWS-vielleicht, weil die Module nicht nest für Zwecke der kind_of??

Tut mir Leid, ich weiß nicht, Module sehr gut in Ruby, aber auf jeden Fall die Basisklasse wird StandardError.

UPDATE:Durch die Art und Weise, aus der ruby-docs:

obj.kind_of?(Klasse) => wahr oder falsch

Gibt true zurück, wenn die Klasse die Klasse von obj, oder wenn eine Klasse eines der Oberklassen des obj oder Module, die in obj.

Wollte nur mal erwähnen:Ich würde Zustimmen, dass dies ein bug in der lib-code.Es sollte wohl Lesen:

      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

Ein Problem, Sie laufen in ist, dass Amazon::AWS::Error::AWSError ist nicht wirklich eine Ausnahme.Wenn raise aufgerufen wird, schaut, um zu sehen, wenn der erste parameter reagiert auf die exception Methode und verwenden Sie das Ergebnis, dass statt.Alles, was eine Unterklasse von Exception zurückkehren wird, selbst wenn exception heißt also, Sie können Dinge tun, wie raise Exception.new("Something is wrong").

In diesem Fall, AWSError hat exception als Attribut-Leser, die es definiert den Wert bei der Initialisierung um so etwas wie Amazon::AWS::Error::SOME_ERROR.Dies bedeutet, dass, wenn Sie anrufen raise Amazon::AWS::Error::AWSError.new(SOME_XML) Ruby endet Aufruf Amazon::AWS::Error::AWSError.new(SOME_XML).exception die gibt eine Instanz von Amazon::AWS::Error::SOME_ERROR.Wie gezeigt, durch eine der anderen Responder, diese Klasse ist eine direkte Unterklasse von StandardError anstatt eine Unterklasse einer gemeinsamen Amazon-Fehler.Bis dies behoben, Jean-Lösung ist wahrscheinlich Ihre beste Wette.

Ich hoffe, geholfen zu erklären, was tatsächlich passiert hinter den kulissen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top