Exécution de code avant chaque méthode dans une classe (Ruby)

voix
1

Je veux garder une trace de toutes les méthodes qui ont été exécutées sur une instance d'une classe que j'ai construit.

Actuellement, je fais:

class MyClass
    def initialize
        @completed = []
    end

    # Sends a welcome and information pack to the person who requested it
    def one_of_many_methods
    unless @completed.include? __method__
            # Do methody things
            @completed.push __method__
        end
    end
    alias :another_name :one_of_many_methods
    # Calling myClassInstance.another_name will insert
    # :one_of_many_methods into @completed.
    # Methody things should not now be done if .another_name
    # or .one_of_many_methods is called.
end

Mais cela devient très laborieux quand j'ai beaucoup de méthodes dans ma classe. Je me répète! Y at-il un moyen de suivre les méthodes appelés et leur permettent seulement d'être appelé une fois, comme je le fais ci-dessus, mais sans avoir à répéter ce bloc dans chaque méthode?

Merci!

(PS. J'utilise Ruby 1.9)

Créé 09/08/2011 à 03:07
source utilisateur
Dans d'autres langues...                            


4 réponses

voix
2

method_missing


Il y a des cadres qui vont faire des choses comme cela, mais pour répondre à votre question, oui, il y a un moyen facile.

Et la manière facile de n'écrire le code une fois est à toute la classe avant la fin et la mise en œuvre method_missing. Vous pouvez ensuite découvrir les véritables méthodes une à la fois que chacun est découvert « manquer » avec un premier appel.

Créé 09/08/2011 à 03:15
source utilisateur

voix
7

Cela sonne comme le cas d'utilisation parfaite pour un proxy objet. Heureusement, la nature dynamique de Ruby rend la mise en œuvre assez facile:

class ExecuteOnceProxy

  def initialize(obj)
    @obj = obj
    @completed = []
  end

  def method_missing(method, *args)
    unless @completed.include?(method)
      args.empty? ? @obj.send(method) : @obj.send(method, args)
      @completed << method
    end
  end
end

Votre proxy simplement Initialiser en passant l'objet d'origine dans le constructeur:

proxy = ExecuteOnceProxy.new(my_obj)
Créé 09/08/2011 à 03:22
source utilisateur

voix
1

Je pense qu'il ya une nouvelle solution pour votre question.

Il y a quelques fois, Tobias Pfeiffer a publié after_do petit bijou

Créé 16/02/2014 à 13:56
source utilisateur

voix
0

Ce n'est pas une réponse parce que je n'ai pas assez réputation pour commenter, mais s'il vous plaît noter que le @emboss de réponse a affiché une erreur dans ce (étoile manquante).

args.empty? ? @obj.send(method) : @obj.send(method, args)

devrait être

args.empty? ? @obj.send(method) : @obj.send(method, *args)

sinon la méthode recevra un seul arg: un tableau des args que vous avez essayé de le transmettre.

Créé 21/09/2015 à 12:56
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more