2017-01-03 1 views
4

J'apprends comment utiliser Module.prepend au lieu de alias_method_chain dans mon code Ruby, et je l'ai remarqué que certaines personnes utilisent send pour appeler (example):Pourquoi les gens utilisent `Module.send (: prepend, ...)`?

ActionView::TemplateRenderer.send(:prepend, 
    ActionViewTemplateRendererWithCurrentTemplate) 

Alors que d'autres appellent directement (example) :

ActionView::TemplateRenderer.prepend(ActionViewTemplateRendererWithCurrentTemplate) 

Et, bien que je ne l'ai pas vu quelqu'un utiliser ce style, je pense de la documentation que vous pouvez même écrire ce dans le module vous préfixer de:

module ActionViewTemplateRendererWithCurrentTemplate 
    # Methods you're overriding go here 

    prepend_features ActionView::TemplateRenderer 
end 

Y a-t-il une différence entre ces trois styles? Y a-t-il une raison de favoriser l'un par rapport aux autres?

+3

Probablement les gens l'écrivent encore de cette façon à cause des «vieilles habitudes», puisque #include et #prepend étaient des méthodes privées avant Ruby 2.1. – Matheno

+1

'prepend_features' est une méthode de hook qui est appelée par' prepend' et généralement * non * prévue ni conçue pour être appelée directement. –

Répondre

5

Module#prepend était added à Ruby version 2.0.0.

Il a été ajouté en tant que méthode privée , avec le cas d'utilisation prévue être dans le format suivant:

module Foo 
    # ... 
end 

class Bar 
    prepend Foo 

    # ... The rest of the class definition ... 
end 

Cependant, il est vite apparu que dans de nombreux cas, les gens voulaient préfixer un module une classe sans définir d'autres aspects de la classe (dans cette section de code). Par conséquent, le modèle suivant est devenu commun:

Bar.send(:prepend, Foo) 

En la version Ruby 2.1.0, cette question a été abordée par making Module#prepend a public method - donc vous pouvez maintenant simplement écrire ceci comme:

Bar.prepend(Foo) 

Cependant, notez que si vous écrivez une bibliothèque qui est nécessaire pour soutenir Ruby 2.0.0 (même si official support ended le 24 février 2016), alors vous devez malheureusement s'en tenir à l'ancienne approche .send(:prepend, ...).

Module#include (qui a été dans la langue Ruby depuis sa création) était également une méthode privée dans la version <= 2.0.0, et a été rendu public en 2.1.0.