Je n'arrive pas à trouver beaucoup d'informations sur les classes d'exceptions personnalisées.
Ce que je sais
Vous pouvez déclarer votre classe d'erreur personnalisée et la laisser hériter de StandardError
, afin qu'elle puisse être rescue
d:
class MyCustomError < StandardError
end
Cela vous permet de l'augmenter en utilisant:
raise MyCustomError, "A message"
et plus tard, recevez ce message lors du sauvetage
rescue MyCustomError => e
puts e.message # => "A message"
Ce que je ne sais pas
Je veux donner à mon exception des champs personnalisés, mais je veux hériter de l' message
attribut de la classe parent. J'ai découvert la lecture sur ce sujet qui @message
n'est pas une variable d'instance de la classe d'exception, alors je crains que mon héritage ne fonctionnera pas.
Quelqu'un peut-il me donner plus de détails à ce sujet? Comment implémenter une classe d'erreur personnalisée avec un object
attribut? Est-ce que ce qui suit est correct:
class MyCustomError < StandardError
attr_reader :object
def initialize(message, object)
super(message)
@object = object
end
end
Puis:
raise MyCustomError.new(anObject), "A message"
obtenir:
rescue MyCustomError => e
puts e.message # => "A message"
puts e.object # => anObject
fonctionnera-t-il, et si c'est le cas, est-ce la bonne façon de faire les choses?
rescue Exception => e
. Il est plus large que la valeur par défautrescue => e
qui s'étend deStandardError
et capture tout, y compris Ctrl + C. Je feraisrescue MyCustomError => e
.Réponses:
raise
définit déjà le message afin que vous n'ayez pas à le passer au constructeur:J'ai remplacé
rescue Exception
parrescue MyCustomError
, voir Pourquoi est-ce un mauvais style de `sauver Exception => e` dans Ruby? .la source
rescue Exception
, mais pourquoi pasrescue MyCustomError
?raise MyCustomError, "a message"
sansnew
, "un message" ne sera pas défini.Étant donné ce que la documentation de base de ruby
Exception
, dont toutes les autres erreurs héritent, indique à propos de#message
http://ruby-doc.org/core-1.9.3/Exception.html#method-i-message
J'opterais pour la redéfinition
to_s
/to_str
ou l'initialiseur. Voici un exemple où nous voulons savoir, d'une manière principalement lisible par l'homme, quand un service externe n'a pas réussi à faire quelque chose.REMARQUE: La deuxième stratégie ci-dessous utilise les méthodes de jolies chaînes de rails, telles que
demodualize
, qui peuvent être un peu compliquées et donc potentiellement imprudentes à faire dans une exception. Vous pouvez également ajouter plus d'arguments à la signature de la méthode, si vous en avez besoin.Remplacer la stratégie #to_s et non #to_str, cela fonctionne différemment
Sortie de la console
Remplacement de la stratégie #initialize
C'est la stratégie la plus proche des implémentations que j'ai utilisées dans les rails. Comme indiqué ci-dessus, il utilise le
demodualize
,underscore
et leshumanize
ActiveSupport
méthodes. Mais cela pourrait être facilement supprimé, comme dans la stratégie précédente.Sortie de la console
Outil de démonstration
Ceci est une démonstration pour montrer le sauvetage et la messagerie de l'implémentation ci-dessus. La classe levant les exceptions est une fausse API pour Cloudinary. Il suffit de vider l'une des stratégies ci-dessus dans votre console de rails, puis celle-ci.
la source
Votre idée est juste, mais la façon dont vous l'appelez est fausse. Ça devrait être
la source
raise
mot - clé ou quelque chose.initialize
pour prendre deux arguments.new
transmet les arguments àinitialize
.raise(BillRowError.new(:roamingcalls, @index), "Roaming Calls field missing")
. Il appelle doncraise
avec deux paramètres: un nouvelBillRowError
objet et son message. Je suis juste confus par la syntaxe ... Sur d'autres tutoriels, je le vois toujours comme ceci:raise Error, message
raise
; c'est assez flexible. Le problème est que vous avez décidéinitialize
de prendre deux arguments et n'en avez donné qu'un. Regardez dans votre exemple.BillRowError.new(:roamingcalls, @index)
reçoit deux arguments.Je voulais faire quelque chose de similaire. Je voulais passer un objet à #new et définir le message en fonction d'un traitement de l'objet passé. Les travaux suivants.
Notez que si vous ne déclarez pas,
attr_accessor :message
cela ne fonctionnera pas. Pour résoudre le problème du PO, vous pouvez également passer le message comme argument supplémentaire et stocker tout ce que vous voulez. La partie cruciale semble être le #message.la source