• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
Créer une API simpliste en Go
Créer une API simpliste en Go
16 juillet 2015
Création d’un jeu en CSS
Création d’un jeu en CSS
16 décembre 2015
Ressources > Articles techniques > Du bon usage des exceptions en Ruby

Du bon usage des exceptions en Ruby

Écrit par Martin C.

Les exceptions servent, comme leur nom l’indique, à gérer des erreurs au caractère rare et imprévu.

Elles n’ont pas vocation à gérer des erreurs prévisibles comme une erreur de saisie d’un utilisateur par exemple.

Venons-en rapidement aux faits :

begin
  3 + '4'
rescue => e
  puts e.class
  puts e.message
  puts e.trace
end

Nous renverra:

TypeError
String can't be coerced into Fixnum
./exceptions.rb:4:in `+'
./exceptions.rb:4:in `<main>'

On a donc une erreur de la classe TypeError. Si on regarde la classe parente de TypeError il s’agit de StandardError. Cette classe est en fait la classe par défaut utilisée dans notre rescue.

Notre code revient donc à :

begin
  3 + '4'
rescue StandardError => e
  puts e.class
  puts e.message
  puts e.trace
end

Il est fortement déconseillé d’attraper des erreurs en dehors des sous-classes de StandardError car elles sont utilisées par le système. Par exemple, on y retrouve NoMemoryError, LoadError ou encore SystemExit pour n’en citer que quelques-unes.

On comprend mieux pourquoi les attraper pourrait avoir des effets de bords. Quelques exemples :

begin
  require 'foo'
rescue Exception
  puts $!
end

Ici, on attrape l’exception de type LoadError, ce qui risque de masquer le problème de chargement de notre fichier.
À noter l’utilisation de la variable globale $! qui récupère automatiquement la dernière exception.

Autre exemple :

while true
  puts "Say quit to esc"
  begin
    str = gets
    exit if "quit" == str.chomp
  rescue Exception => e
    puts "Exception #{e.class}"
  end
end

Bon courage pour quitter, le rescue attrapera l’exception SystemExit si vous tapez quit mais également Interrupt si vous faites un ^C.

À part pour faire une lib de debug ou autre type de wrapper ne faites pas de rescue Exception. Si vous avez besoin d’un wrapper, pensez à relancer l’exception :

begin
  require 'foo'
 rescue Exception => e
  # j'attrape tout, mais je sais ce que je fais
  puts $!
  raise e
end

Lorsque vous avez besoin de vous assurer qu’un traitement sera réalisé même si une exception survient vous pouvez utiliser ensure :

require 'tempfile'

begin
  file = Tempfile.new('a')
  raise StandardError.new("ugh")
rescue => e
  puts $!
  raise e
ensure
  file.close
  file.unlink
end

Notre section ensure va s’assurer que le fichier est bien fermé et supprimé. J’ai volontairement re-lancé l’exception pour montrer que même si le rescue relance l’exception, le passage dans le ensure est garanti.

Bien entendu, vous pouvez créer votre propre exception comme une classe classique :

class MyOwnException < Exception; end

raise MyOwnException.new('foo')

Si vous souhaitez attraper plusieurs types d’exception sans distinction, vous pouvez parfaitement écrire :

require 'tempfile'

begin
  file = Tempfile.new('a')
  raise ArgumentError.new("ugh")
rescue ArgumentError, ZeroDivisionError => e
  puts $!
  raise e
ensure
  file.close
  file.unlink
end

Vous pouvez également gérer des comportements différents avec plusieurs instructions rescue :

require 'tempfile'

begin
  file = Tempfile.new('a')
  raise ArgumentError.new("ugh")
rescue ArgumentError => e
  puts $!
  # je renvoie l'erreur uniquement si c'est une exception de type ArgumentError
  raise e
rescue ZeroDivisionError => e
  puts $!
ensure
  file.close
  file.unlink
end

Pour connaître la liste des exceptions disponibles, je vous ai préparé quelques lignes pour parcourir les différentes classes existantes et les afficher sous forme d’arbre :

def subclasses_tree(klass, level = 0)
  puts level.zero? ? klass.to_s : "#{' ' * (4 * (level - 1))}├── #{klass}"
  descendants_of(klass).select { |k| k.superclass == klass }.each do |k|
    subclasses_tree(k, level + 1)
  end
end

def descendants_of(klass)
  ObjectSpace.each_object(Class).select { |k| k < klass }
end

subclasses_tree(Exception)

Résultat :

Exception
├── MonitorMixin::ConditionVariable::Timeout
├── SystemStackError
├── NoMemoryError
├── SecurityError
├── ScriptError
    ├── NotImplementedError
    ├── LoadError
        ├── Gem::LoadError
            ├── Gem::ConflictError
    ├── SyntaxError
├── StandardError
    ├── FiberError
    ├── ThreadError
    ├── Math::DomainError
    ├── LocalJumpError
    ├── IOError
        ├── EOFError
    ├── RegexpError
    ├── ZeroDivisionError
    ├── SystemCallError
        ├── Errno::ERPCMISMATCH
        ├── Errno::EPROGUNAVAIL
        ├── Errno::EPROGMISMATCH
        ├── Errno::EPROCUNAVAIL
        ├── Errno::EPROCLIM
        ├── Errno::ENOTSUP
        ├── Errno::ENOATTR
        ├── Errno::ENEEDAUTH
        ├── Errno::EFTYPE
        ├── Errno::EBADRPC
        ├── Errno::EAUTH
        ├── Errno::EOWNERDEAD
        ├── Errno::ENOTRECOVERABLE
        ├── Errno::ECANCELED
        ├── Errno::EDQUOT
        ├── Errno::ESTALE
        ├── Errno::EINPROGRESS
            ├── IO::EINPROGRESSWaitWritable
            ├── IO::EINPROGRESSWaitReadable
        ├── Errno::EALREADY
        ├── Errno::EHOSTUNREACH
        ├── Errno::EHOSTDOWN
        ├── Errno::ECONNREFUSED
        ├── Errno::ETIMEDOUT
        ├── Errno::ETOOMANYREFS
        ├── Errno::ESHUTDOWN
        ├── Errno::ENOTCONN
        ├── Errno::EISCONN
        ├── Errno::ENOBUFS
        ├── Errno::ECONNRESET
        ├── Errno::ECONNABORTED
        ├── Errno::ENETRESET
        ├── Errno::ENETUNREACH
        ├── Errno::ENETDOWN
        ├── Errno::EADDRNOTAVAIL
        ├── Errno::EADDRINUSE
        ├── Errno::EAFNOSUPPORT
        ├── Errno::EPFNOSUPPORT
        ├── Errno::EOPNOTSUPP
        ├── Errno::ESOCKTNOSUPPORT
        ├── Errno::EPROTONOSUPPORT
        ├── Errno::ENOPROTOOPT
        ├── Errno::EPROTOTYPE
        ├── Errno::EMSGSIZE
        ├── Errno::EDESTADDRREQ
        ├── Errno::ENOTSOCK
        ├── Errno::EUSERS
        ├── Errno::EILSEQ
        ├── Errno::EOVERFLOW
        ├── Errno::EBADMSG
        ├── Errno::EMULTIHOP
        ├── Errno::EPROTO
        ├── Errno::ENOLINK
        ├── Errno::EREMOTE
        ├── Errno::ENOSR
        ├── Errno::ETIME
        ├── Errno::ENODATA
        ├── Errno::ENOSTR
        ├── Errno::EIDRM
        ├── Errno::ENOMSG
        ├── Errno::ELOOP
        ├── Errno::ENOTEMPTY
        ├── Errno::ENOSYS
        ├── Errno::ENOLCK
        ├── Errno::ENAMETOOLONG
        ├── Errno::EDEADLK
        ├── Errno::ERANGE
        ├── Errno::EDOM
        ├── Errno::EPIPE
        ├── Errno::EMLINK
        ├── Errno::EROFS
        ├── Errno::ESPIPE
        ├── Errno::ENOSPC
        ├── Errno::EFBIG
        ├── Errno::ETXTBSY
        ├── Errno::ENOTTY
        ├── Errno::EMFILE
        ├── Errno::ENFILE
        ├── Errno::EINVAL
        ├── Errno::EISDIR
        ├── Errno::ENOTDIR
        ├── Errno::ENODEV
        ├── Errno::EXDEV
        ├── Errno::EEXIST
        ├── Errno::EBUSY
        ├── Errno::ENOTBLK
        ├── Errno::EFAULT
        ├── Errno::EACCES
        ├── Errno::ENOMEM
        ├── Errno::EAGAIN
            ├── IO::EAGAINWaitWritable
            ├── IO::EAGAINWaitReadable
        ├── Errno::ECHILD
        ├── Errno::EBADF
        ├── Errno::ENOEXEC
        ├── Errno::E2BIG
        ├── Errno::ENXIO
        ├── Errno::EIO
        ├── Errno::EINTR
        ├── Errno::ESRCH
        ├── Errno::ENOENT
        ├── Errno::EPERM
        ├── Errno::NOERROR
    ├── EncodingError
        ├── Encoding::ConverterNotFoundError
        ├── Encoding::InvalidByteSequenceError
        ├── Encoding::UndefinedConversionError
        ├── Encoding::CompatibilityError
    ├── RuntimeError
        ├── Gem::Exception
            ├── Gem::VerificationError
            ├── Gem::RubyVersionMismatch
            ├── Gem::RemoteSourceException
            ├── Gem::RemoteInstallationSkipped
            ├── Gem::RemoteInstallationCancelled
            ├── Gem::RemoteError
            ├── Gem::OperationNotSupportedError
            ├── Gem::InvalidSpecificationException
            ├── Gem::InstallError
            ├── Gem::ImpossibleDependenciesError
            ├── Gem::GemNotFoundException
                ├── Gem::SpecificGemNotFoundException
            ├── Gem::FormatException
            ├── Gem::FilePermissionError
            ├── Gem::EndOfYAMLException
            ├── Gem::DocumentError
            ├── Gem::GemNotInHomeException
            ├── Gem::DependencyRemovalException
            ├── Gem::DependencyError
                ├── Gem::UnsatisfiableDependencyError
                ├── Gem::DependencyResolutionError
            ├── Gem::CommandLineError
    ├── NameError
        ├── NoMethodError
    ├── RangeError
        ├── FloatDomainError
    ├── IndexError
        ├── StopIteration
        ├── KeyError
    ├── ArgumentError
        ├── UncaughtThrowError
        ├── Gem::Requirement::BadRequirementError
    ├── TypeError
├── SignalException
    ├── Interrupt
├── fatal
├── SystemExit
    ├── Gem::SystemExitException

Vous savez tout, bonne gestion d’exceptions avec Ruby !

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter