سؤال

أنا جديدة على روبي, لذا لدي بعض المشاكل في فهم هذا غريب استثناء المشكلة أواجه.أنا باستخدام روبي-aaws جوهرة للوصول إلى الأمازون ECS: http://www.caliban.org/ruby/ruby-aws/.هذا يحدد فئة الأمازون::AWS:خطأ:

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, ، الانقاذ كتلة يحصل تشغيلها.يبدو أن أمازون::AWS::خطأ ليس الفائقة التي تم إنشاؤها خطأ - أعتقد بما انها وحدة كل ما هو فئة فرعية من ذلك ؟ بالتأكيد إذا كنت تفعل:

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

يقول true, التي لا تجد مربكة ، وخاصة في ضوء هذا:

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

ما يجري و كيف من المفترض أن فصل أوس أخطاء من نوع آخر من الأخطاء ؟ يجب أن أفعل شيئا مثل:

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 من هي ولدت استثناء أنواع فقط ترث من StandardError.

للتوضيح لدي سؤالان:

  1. لماذا NameError, روبي بنيت في الاستثناء ، kind_of?(Amazon::AWS::Error), الذي هو وحدة ؟
    الجواب: قلت include Amazon::AWS::Error في الجزء العلوي من الملف ظنا منه أنه نوع من مثل جافا استيراد أو 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]

kind_of?يقول لك نعم, خطأ لا تمتلك كل من::B::خطأ في السلوك (وهو أمر طبيعي لأنه يتضمن::B::خطأ) أنها لا تشمل كل سلوك من::B وبالتالي ليس من A::B نوع.(بطة في الكتابة)

الآن هناك فرصة جيدة جدا أن روبي-أوس تعيد فتح أحد المتفوقة من NameError ويشمل الأمازون::AWS:خطأ في هناك.(القرد الترقيع)

يمكنك معرفة برمجيا حيث وحدة تدرج في التسلسل الهرمي التالي :

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 الطبقة تبدو أكثر مثل مصنع صف لي :/ )

ليس لدي روبي-aws هنا caliban حظر الموقع من قبل الشركة جدار الحماية لذلك لا أستطيع اختبار أبعد من ذلك بكثير.

بشأن ما يلي :قد يكون الشيء به القرد الترقيع على StandardError الهرمي.أنا لست متأكدا بعد الآن ولكن على الأرجح تفعل ذلك في جذر ملف خارج كل السياق بما في ذلك وحدة على الكائن أو الكائن metaclass.(هذا هو ما يمكن أن يحدث في المجلس ، حيث السياق الافتراضي هو كائن غير متأكد حول ملف)

من معول على وحدات :

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 قاعدة الطبقة ، لذلك لن يكون الأمازون::AWS::خطأ على الإطلاق.هو مجرد المعرفة في الوحدة النمطية الذي هو على الارجح السبب في ذلك هو kind_of?الأمازون::AWS::خطأ.ربما ليس kind_of?الأمازون::AWS لأنه ربما وحدات لا عش لأغراض kind_of??

آسف, أنا لا أعرف وحدات جيدا في روبي ، ولكن بالتأكيد الفئة الأساسية ستكون StandardError.

التحديث:بالمناسبة ، من روبي مستندات:

obj.kind_of?(الطبقة) => true أو false

إرجاع true إذا كان الصف فئة من الكائنات ، أو إذا كان الصف واحدا من superclasses من الكائنات أو وحدات المدرجة في الكائنات.

أردت فقط أن تتناغم في:وأود أن نتفق على أن هذا هو خلل في ليب رمز.ربما أنه ينبغي قراءة:

      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 بدلا من كونها فرعية مشتركة الأمازون خطأ.حتى يتم تصحيح جان الحل هو على الأرجح أفضل رهان.

اتمنى التي ساعدت على شرح أكثر من ما هو في الواقع يجري وراء الكواليس.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top