Où définir des types d’erreur personnalisés dans Ruby et / ou Rails?

Existe-t-il une meilleure pratique pour définir des types d’erreur personnalisés dans une bibliothèque Ruby (gem) ou une application Ruby on Rails? Plus précisément:

  1. Où appartiennent-ils structurellement dans le projet? Un fichier séparé, en ligne avec la définition du module / classe correspondant, quelque part ailleurs?
  2. Existe-t-il des conventions établissant quand et quand ne pas créer un nouveau type d’erreur?

Différentes bibliothèques ont des façons différentes de faire les choses, et je n’ai pas remarqué de modèles réels. Certaines bibliothèques utilisent toujours des types d’erreur personnalisés alors que d’autres ne les utilisent pas du tout. certains ont toutes les erreurs étendant StandardError tandis que d’autres ont des hiérarchies nestedes; certains ne sont que des définitions de classes vides, d’autres ont toutes sortes de trucs astucieux.

Oh, et juste parce que j’ai envie d’appeler ces “types d’erreur” est en quelque sorte ambigu, ce que je veux dire c’est ceci:

class AuthenticationError < StandardError; end class InvalidUsername < AuthenticationError; end 

Pour gemmes

J’ai souvent vu que vous définissiez des exceptions de cette manière:

rép_gem / lib / nom_gem / exceptions.rb

et défini comme:

 module GemName class AuthenticationError < StandardError; end class InvalidUsername < AuthenticationError; end end 

un exemple de ceci serait quelque chose comme ceci dans httparty

Pour Ruby on Rails

Placez-les dans votre dossier lib / sous un fichier appelé exceptions.rb, qui ressemblerait à ceci:

 module Exceptions class AuthenticationError < StandardError; end class InvalidUsername < AuthenticationError; end end 

et vous l'utiliseriez comme ceci:

 raise Exceptions::InvalidUsername 

Je pense que pour avoir des fichiers sources cohérents dans votre projet, vous devez définir des erreurs dans la classe dans laquelle ils peuvent les lancer et nulle part ailleurs.

Une certaine hiérarchie peut être utile – les espaces de noms sont efficaces pour garder les chaînes redondantes avec les noms de caractères – mais c’est plus une question de goût – il n’y a pas besoin entre les cas d’exception ‘intentionnels’ et ‘accidentels’.

dans les rails, vous pouvez créer un répertoire app/errors

 # app/errors/foo_error.rb class FooError < StandardError; end 

redémarrer le spring / serveur et il devrait le ramasser

Pour vous assurer que le chargement automatique fonctionne comme prévu dans Rails 4.1.10 pour plusieurs classes d’erreurs personnalisées, vous souhaiterez spécifier des fichiers distincts pour chacun. Cela devrait fonctionner en développement avec son rechargement dynamic.

Voici comment je configure les erreurs dans un projet récent:

Dans lib/app_name/error/base.rb

 module AppName module Error class Base < StandardError; end end end 

et dans les erreurs personnalisées suivantes, comme dans lib/app_name/error/bad_stuff.rb

 module AppName module Error class BadStuff < ::AppName::Error::Base; end end end 

Vous devriez alors pouvoir appeler vos erreurs via:

  raise AppName::Error::BadStuff.new("Bad stuff just happened") 

C’est une vieille question, mais je voulais partager la manière dont je gère les erreurs personnalisées dans Rails, notamment en joignant des messages d’erreur, en testant et en gérant les problèmes avec les modèles ActiveRecord .

Création d’une erreur personnalisée

 class MyClass # create a custome error class MissingRequirement < StandardError; end def my_instance_method raise MyClass::MissingRequirement, "My error msg" unless true end end 

Test (minitest)

 test "should raise MissingRequirement if ____ is missing" # should raise an error error = assert_raises(MyClass::MissingRequirement) { MyClass.new.my_instance_method } assert error.message = "My error msg" end 

Avec ActiveRecord

Je pense que cela vaut la peine de noter que si vous travaillez avec un modèle ActiveRecord , un modèle populaire consiste à append une erreur au modèle comme décrit ci-dessous, afin que vos validations échouent:

 def MyModel < ActiveRecord::Base validate :code_does_not_contain_hyphens def code_does_not_contain_hyphens errors.add(:code, "cannot contain hyphens") if code.include?("-") end end 

Lorsque les validations sont exécutées, cette méthode sera ActiveRecord::RecordInvalid la classe d'erreur ActiveRecord::RecordInvalid d' ActiveRecord::RecordInvalid et entraînera l'échec des validations.

J'espère que cela t'aides!