Lors de la mise à niveau de ruby de 1.8.7 à 1.9.3, si vous spécifiez une chaîne de caractères vide dans l'argument de Time.parse, une exception se produira.
[EXCEPTION] ArgumentError: Se produit lorsque la date reçoit une chaîne vide. Avant la version 1.9.2, aucune exception n'était déclenchée et une instance de Time représentant l'heure actuelle était renvoyée.
Manuel de référence de Ruby 1.9.2 Time.parse
Comme il y avait trop d'endroits où des caractères vides étaient spécifiés dans Time.parse et que c'était difficile à corriger, j'ai décidé d'appliquer un patch de singe à Time.parse pour le résoudre.
Lorsqu'une chaîne de caractères vide est spécifiée, Time.now est renvoyé, et à part cela, il s'agit d'un processus de type remplacement qui appelle la méthode d'analyse de la classe intégrée.
class Time
  class << self
    alias_method :__parse__, :parse
    private :__parse__
    def parse(time)
      if time.empty?
        #Renvoie l'heure actuelle
        Time.now
      else
        #Heure de classe intégrée.Analyse des appels
        __parse__(time)
      end
    end
  end
end
Il est également possible de le définir avec self.parse.
class Time
  class << self
    alias_method :__parse__, :parse
    private :__parse__
  end
  def self.parse(time)
    if time.empty?
      #Renvoie l'heure actuelle
      Time.now
    else
      #Heure de classe intégrée.Analyse des appels
      __parse__(time)
    end
  end
end
Je voulais vérifier les chaînes vides tout en profitant de la classe intégrée Time, j'ai donc pensé que je devrais hériter de Time et le remplacer. Cependant, lors de l'héritage, il est nécessaire de faire du nom de classe un alias et de changer tous les endroits où Time.parse (arg) est utilisé par le nouveau nom de classe. J'ai abandonné parce que c'était la fin de l'histoire.
Ensuite, j'ai examiné le patch de singe. Cookpad a également pris en charge le patch monkey, alors j'y ai fait référence. (Il a été écrit que vous ne devriez pas le faire autant que possible.) Comment appliquer des correctifs de singe dans les applications Ruby on Rails
J'ai préparé une classe d'extension pour Time et je l'ai définie comme suit.
class Time
  def self.parse(time)
    if time.empty?
      Time.now
    else
      Time.parse(time)
    end
  end
end
Cependant, c'est une erreur. C'est également un problème car la classe d'extension Time.parse a été appelée tout le temps et est devenue une situation de boucle infinie.
irb(main):002:0> Time.parse('2020-01-01 12:34:56')
SystemStackError: stack level too deep
	from /usr/local/lib/ruby/1.9.1/irb/workspace.rb:80
Maybe IRB bug!
J'ai recherché s'il y avait un moyen d'appeler la classe d'extension Time.parse à partir du code précédent et je me suis référé à l'article suivant. Remplacer la méthode existante ](https://qiita.com/umanoda/items/33613b94ccabf7b1f851)
En utilisant ʻalias_method et en changeant le nom de la méthode de parsede la classe d'extension Time enparse`, il semblait que la boucle infinie précédente pouvait être évitée.
Pour être sûr, définissez-le comme «privé» afin qu'il ne soit pas appelé de l'extérieur.
class Time
  alias_method :__parse__, :parse
  private :__parse__
  def self.parse(time)
    if time.empty?
      Time.now
    else
      Time.parse(time)
    end
  end
end
Ensuite, j'obtiens une erreur s'il n'y a pas de méthode parse.
alias_medhod n'a pas pu être appliqué car l'analyse est une méthode de classe.
bundle exec rails c
`alias_method': undefined method `parse' for class `Time' (NameError)
J'ai fait référence à ce qui suit sur la façon d'alias_method une méthode de classe. Ajouter un alias à la méthode de classe
Il pourrait être appliqué en définissant ʻalias_method` dans la classe << self. Le formulaire final est ici.
class Time
  class << self
    alias_method :__parse__, :parse
    private :__parse__
  end
  def self.parse(time)
    if time.empty?
      Time.now
    else
      __parse__(time)
    end
  end
end
Il est également possible de définir la méthode d'analyse dans la classe << self comme indiqué ci-dessous. Dans ce cas, le soi n'est pas nécessaire.
class Time
  class << self
    alias_method :__parse__, :parse
    private :__parse__
    def parse(time)
      if time.empty?
        Time.now
      else
        __parse__(time)
      end
    end
  end
end
Je pense que peu d'environnements utilisent maintenant ruby 1.8.7, mais j'espère que cela sera utile pour mettre à jour le code hérité. De plus, je pense que cela sera utile pour la méthode de patch monkey de la classe intégrée, donc j'espère que cela aidera.
Manuel de référence de Ruby 1.9.2 Time.parse
Comment appliquer des correctifs de singe dans les applications Ruby on Rails
Remplacer la méthode existante ](https://qiita.com/umanoda/items/33613b94ccabf7b1f851)
Ajouter un alias à la méthode de classe
Recommended Posts