> rescues happen exactly once per exception handling block. Awesome, great to know that and for the explanation on why both methods yield different results. I totally forgot RuntimeError is an StandardError. Em ter., 29 de out. de 2024 às 15:07, Austin Ziegler escreveu: > RuntimeError is a descendant of StandardError, and rescues happen exactly > once per exception handling block. > > That is, your first code example will never hit RuntimeError because it's > swallowed by the implicit StandardError. > > Here's a class tree of Exception from my local irb: > > - Exception > |- ErrorHighlight::Spotter::NonAscii > |- IRB::Abort > |- IRB::LoadAbort > |- NoMemoryError > |- ScriptError > | |- LoadError > | | `- Gem::LoadError > | | |- Gem::ConflictError > | | `- Gem::MissingSpecError > | | `- Gem::MissingSpecVersionError > | |- NotImplementedError > | `- SyntaxError > |- SecurityError > |- SignalException > | `- Interrupt > |- StandardError > | |- ArgumentError > | | |- Gem::Requirement::BadRequirementError > | | |- IO::Buffer::MaskError > | | `- UncaughtThrowError > | |- EncodingError > | | |- Encoding::CompatibilityError > | | |- Encoding::ConverterNotFoundError > | | |- Encoding::InvalidByteSequenceError > | | `- Encoding::UndefinedConversionError > | |- FiberError > | |- Fiddle::Error > | | |- Fiddle::ClearedReferenceError > | | `- Fiddle::DLError > | |- Gem::Molinillo::ResolverError > | | |- Gem::Molinillo::CircularDependencyError > | | |- Gem::Molinillo::NoSuchDependencyError > | | `- Gem::Molinillo::VersionConflict > | |- Gem::TSort::Cyclic > | |- IOError > | | |- EOFError > | | `- IO::TimeoutError > | |- IRB::CantChangeBinding > | |- IRB::CantReturnToNormalMode > | |- IRB::Command::CommandArgumentError > | |- IRB::IllegalParameter > | |- IRB::IrbAlreadyDead > | |- IRB::IrbSwitchedToCurrentThread > | |- IRB::NoSuchJob > | |- IRB::RubyLex::TerminateLineInput > | |- IRB::SourceFinder::EvaluationError > | |- IRB::UndefinedPromptMode > | |- IRB::UnrecognizedSwitch > | |- IndexError > | | |- KeyError > | | `- StopIteration > | | |- ClosedQueueError > | | `- Ractor::ClosedError > | |- JSON::JSONError > | | |- JSON::GeneratorError > | | |- JSON::MissingUnicodeSupport > | | `- JSON::ParserError > | | `- JSON::NestingError > | | `- JSON::CircularDatastructure > | |- LocalJumpError > | |- Math::DomainError > | |- NameError > | | `- NoMethodError > | |- NoMatchingPatternError > | | `- NoMatchingPatternKeyError > | |- RangeError > | | `- FloatDomainError > | |- RegexpError > | | `- Regexp::TimeoutError > | |- Reline::ConfigEncodingConversionError > | |- Reline::Terminfo::TerminfoError > | |- Ripper::TokenPattern::Error > | | |- Ripper::TokenPattern::CompileError > | | `- Ripper::TokenPattern::MatchError > | |- RuntimeError > | | |- FrozenError > | | |- Gem::Exception > | | | |- Gem::CommandLineError > | | | |- Gem::DependencyError > | | | | |- Gem::DependencyResolutionError > | | | | `- Gem::UnsatisfiableDependencyError > | | | |- Gem::DependencyRemovalException > | | | |- Gem::DocumentError > | | | |- Gem::EndOfYAMLException > | | | |- Gem::FilePermissionError > | | | |- Gem::FormatException > | | | |- Gem::GemNotFoundException > | | | | `- Gem::SpecificGemNotFoundException > | | | |- Gem::GemNotInHomeException > | | | |- Gem::ImpossibleDependenciesError > | | | |- Gem::InstallError > | | | | `- Gem::RuntimeRequirementNotMetError > | | | |- Gem::InvalidSpecificationException > | | | |- Gem::OperationNotSupportedError > | | | |- Gem::RemoteError > | | | |- Gem::RemoteInstallationCancelled > | | | |- Gem::RemoteInstallationSkipped > | | | |- Gem::RemoteSourceException > | | | |- Gem::RequestSet::Lockfile::ParseError > | | | |- Gem::RubyVersionMismatch > | | | |- Gem::UninstallError > | | | |- Gem::UnknownCommandError > | | | |- Gem::VerificationError > | | | `- Gem::WebauthnVerificationError > | | |- IO::Buffer::AccessError > | | |- IO::Buffer::AllocationError > | | |- IO::Buffer::InvalidatedError > | | |- IO::Buffer::LockedError > | | |- RDoc::Error > | | |- Ractor::Error > | | | |- Ractor::IsolationError > | | | |- Ractor::MovedError > | | | |- Ractor::RemoteError > | | | `- Ractor::UnsafeError > | | `- Reline::Config::InvalidInputrc > | |- SystemCallError > | | |- Errno::E2BIG > | | |- Errno::EACCES > | | |- Errno::EADDRINUSE > | | |- Errno::EADDRNOTAVAIL > | | |- Errno::EAFNOSUPPORT > | | |- Errno::EAGAIN > | | | |- IO::EAGAINWaitReadable > | | | `- IO::EAGAINWaitWritable > | | |- Errno::EALREADY > | | |- Errno::EAUTH > | | |- Errno::EBADARCH > | | |- Errno::EBADEXEC > | | |- Errno::EBADF > | | |- Errno::EBADMACHO > | | |- Errno::EBADMSG > | | |- Errno::EBADRPC > | | |- Errno::EBUSY > | | |- Errno::ECANCELED > | | |- Errno::ECHILD > | | |- Errno::ECONNABORTED > | | |- Errno::ECONNREFUSED > | | |- Errno::ECONNRESET > | | |- Errno::EDEADLK > | | |- Errno::EDESTADDRREQ > | | |- Errno::EDEVERR > | | |- Errno::EDOM > | | |- Errno::EDQUOT > | | |- Errno::EEXIST > | | |- Errno::EFAULT > | | |- Errno::EFBIG > | | |- Errno::EFTYPE > | | |- Errno::EHOSTDOWN > | | |- Errno::EHOSTUNREACH > | | |- Errno::EIDRM > | | |- Errno::EILSEQ > | | |- Errno::EINPROGRESS > | | | |- IO::EINPROGRESSWaitReadable > | | | `- IO::EINPROGRESSWaitWritable > | | |- Errno::EINTR > | | |- Errno::EINVAL > | | |- Errno::EIO > | | |- Errno::EISCONN > | | |- Errno::EISDIR > | | |- Errno::ELAST > | | |- Errno::ELOOP > | | |- Errno::EMFILE > | | |- Errno::EMLINK > | | |- Errno::EMSGSIZE > | | |- Errno::EMULTIHOP > | | |- Errno::ENAMETOOLONG > | | |- Errno::ENEEDAUTH > | | |- Errno::ENETDOWN > | | |- Errno::ENETRESET > | | |- Errno::ENETUNREACH > | | |- Errno::ENFILE > | | |- Errno::ENOATTR > | | |- Errno::ENOBUFS > | | |- Errno::ENODATA > | | |- Errno::ENODEV > | | |- Errno::ENOENT > | | |- Errno::ENOEXEC > | | |- Errno::ENOLCK > | | |- Errno::ENOLINK > | | |- Errno::ENOMEM > | | |- Errno::ENOMSG > | | |- Errno::ENOPOLICY > | | |- Errno::ENOPROTOOPT > | | |- Errno::ENOSPC > | | |- Errno::ENOSR > | | |- Errno::ENOSTR > | | |- Errno::ENOSYS > | | |- Errno::ENOTBLK > | | |- Errno::ENOTCONN > | | |- Errno::ENOTDIR > | | |- Errno::ENOTEMPTY > | | |- Errno::ENOTRECOVERABLE > | | |- Errno::ENOTSOCK > | | |- Errno::ENOTSUP > | | |- Errno::ENOTTY > | | |- Errno::ENXIO > | | |- Errno::EOPNOTSUPP > | | |- Errno::EOVERFLOW > | | |- Errno::EOWNERDEAD > | | |- Errno::EPERM > | | |- Errno::EPFNOSUPPORT > | | |- Errno::EPIPE > | | |- Errno::EPROCLIM > | | |- Errno::EPROCUNAVAIL > | | |- Errno::EPROGMISMATCH > | | |- Errno::EPROGUNAVAIL > | | |- Errno::EPROTO > | | |- Errno::EPROTONOSUPPORT > | | |- Errno::EPROTOTYPE > | | |- Errno::EPWROFF > | | |- Errno::ERANGE > | | |- Errno::EREMOTE > | | |- Errno::EROFS > | | |- Errno::ERPCMISMATCH > | | |- Errno::ESHLIBVERS > | | |- Errno::ESHUTDOWN > | | |- Errno::ESOCKTNOSUPPORT > | | |- Errno::ESPIPE > | | |- Errno::ESRCH > | | |- Errno::ESTALE > | | |- Errno::ETIME > | | |- Errno::ETIMEDOUT > | | |- Errno::ETOOMANYREFS > | | |- Errno::ETXTBSY > | | |- Errno::EUSERS > | | |- Errno::EXDEV > | | `- Errno::NOERROR > | |- ThreadError > | |- TypeError > | `- ZeroDivisionError > |- SystemExit > | `- Gem::SystemExitException > |- SystemStackError > `- fatal > > -a > > On Tue, Oct 29, 2024 at 8:48 AM Rodrigo Rosenfeld Rosas via ruby-core < > ruby-core@ml.ruby-lang.org> wrote: > >> Hello, I couldn't find any documentation about the subject, so I thought >> this behavior should be probably documented. >> >> Given the following code: >> >> def raise_error >> raise "runtime error message" >> rescue => e >> "StandardError: #{e.message}" >> rescue RuntimeError => e >> puts "RuntimeError raised: #{e.message}" >> raise StandardError, "standard error message" >> end >> >> # same, but the order of the rescue blocks are inverted >> def raise_error2 >> raise "runtime error message" >> rescue RuntimeError => e >> puts "RuntimeError raised: #{e.message}" >> raise StandardError, "standard error message" >> rescue => e >> "StandardError: #{e.message}" >> end >> >> p ["raise_error", raise_error ] >> >> begin >> p ["raise_error2", raise_error2] >> rescue => e >> puts "raise_error2 raised: #{e.message}" >> end >> >> When we run it, this is the output in Ruby 3.3.5: >> >> ["raise_error", "StandardError: runtime error message"] >> >> RuntimeError raised: runtime error message >> >> raise_error2 raised: standard error message >> >> >> In the first case (raise_error), the code raised from the RuntimeError >> rescue block is rescued by the StandardError block, but when inverting the >> order of the rescue blocks (raise_error2) then this won't happen. >> >> Is this part of the specs? Is this behavior documented somewhere? Could >> this behavior differ in different Ruby implementations and versions? Or can >> we rely on such behavior? >> >> >> This chapter doesn't include such case in its examples: >> >> https://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html >> >> Or this documentation about Exceptions: >> >> https://ruby-doc.org/3.3.5/syntax/exceptions_rdoc.html >> >> Is there a recommended way for wrapping exceptions into a particular one >> and then handling that exception from within the same method rescue blocks? >> Or is this considered a bad practice? >> >> >> ______________________________________________ >> ruby-core mailing list -- ruby-core@ml.ruby-lang.org >> To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org >> ruby-core info -- >> https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/ > > > > -- > Austin Ziegler • halostatue@gmail.com • austin@halostatue.ca > http://www.halostatue.ca/ • http://twitter.com/halostatue >