2 votes

Pourquoi ne puis-je pas sauver cette erreur personnalisée définie à l'intérieur d'une autre classe ?

Je travaille avec Rails 6. J'ai défini une classe d'erreur à l'intérieur de la classe qui la soulève :

class MyClass < ApplicationRecord
  ...

  class CustomError < StandardError
    attr_reader :param

    def initialize(param)
      @param = param
    end
  end
end

J'essaie de le sauver dans le code client, mais cela ne marche pas :

rescue MyClass::CustomError => e

D'autre part, cela soulève uninitialized constant sur CustomError Le résultat est exactement ce à quoi je m'attendais :

rescue CustomError => e

Qu'en est-il de ceci ?

rescue MyClass::CustomError => e
  raise unless e.instance_of? MyClass::CustomError
  # do some real error handling
  ...
end

instance_of? ne reconnaît pas l'erreur et relance.

J'ai même essayé :

class MyClass < ApplicationRecord
  ...
end

class MyClass::CustomError < StandardError
  attr_reader :para
  def initialize(param)
    @param = param
  end
end

Ce n'est pas mieux.

2 choses qui avoir ont travaillé sont tous deux des odeurs de code :

  1. Définition de l'erreur en dehors de la classe contenante, sans espacement des noms (namespacing)

  2. Sauvegarde d'une erreur générique : rescue => e

Il fonctionne également très bien dans MiniTest :

e = assert_raises(MyClass::CustomError) do
  ...
end

On a l'impression que le nom de la classe d'erreur CustomError ne se résout tout simplement pas à MyClass::CustomError dans le code de l'application, mais le code du client a besoin du nom de classe contenant la classe pour la résoudre.

Il est plus probable que je fasse quelque chose d'un peu naïf/stupide !

Informations complémentaires :

  • Ruby 2.7.1
  • Rails 6.0.3.3
  • La classe qui soulève l'erreur et la classe qui la traite sont toutes deux des classes de modèle (ce qui est un peu inhabituel)
  • La classe d'exécution à l'origine de l'erreur est un enfant de MyClass : MyChild < MyClass < ActiveRecord (également inhabituel)

0voto

guy Points 32

Pour ceux qui ne le savent pas, Rails 4.2 a ajouté Spring, qui garde l'application en mémoire lorsque vous la terminez (pour accélérer les temps de démarrage), et Rails 5.2 a ajouté Bootsnap, qui met en cache le code optimisé. L'un comme l'autre peuvent laisser traîner du code inchangé et provoquer des bogues bizarres.

L'un d'eux m'a mordu. Il semble que Bootsnap soulevait l'erreur mais ne la rendait pas visible à l'extérieur. MyClass . La suppression du cache a tout réglé :

rm -rf tmp/cache/bootsnap-compile-cache/
rm tmp/cache/bootsnap-load-path-cache

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X