J'ai donc un moteur Rails 3.0 (gem).
Il fournit un contrôleur à app/controllers/advanced_controller.rb, et une aide correspondante à app/helpers/advanced_helper.rb. (Et quelques vues bien sûr).
Jusqu'ici tout va bien, le contrôleur/helper/views sont juste automatiquement disponibles dans l'application utilisant la gemme, super.
Mais je veux permettre à l'application locale sélective de remplacer les méthodes d'aide d'AdvancedHelper dans le moteur (et idéalement être capable d'appeler 'super'). C'est une chose assez raisonnable à permettre, n'est-ce pas, une conception parfaitement raisonnable (et je pense commune) ?
Le problème, c'est que je n'arrive pas à trouver le moyen de le faire fonctionner. Si l'application définit son propre app/helpers/advanced_helper.rb (AdvancedHelper), alors celui du moteur n'est jamais chargé du tout -- donc cela fonctionnerait si vous vouliez remplacer TOUTES les méthodes d'aide là-dedans (sans appeler super), mais pas si vous voulez juste en remplacer une.
C'est assez logique en fait, donc je choisis un nom différent. Appelons mon aide locale ./app/helpers/local_advanced_helper.rb (LocalAdvancedHelper). Cette aide est chargée, si je mets une méthode là-dedans qui n'était pas dans l'AdvancedHelper du moteur original, elle est disponible pour les vues.
Mais si j'y place une méthode portant le même nom que celle de l'AdvancedHelper du moteur... ma méthode locale n'est JAMAIS appelée. C'est comme si l'AdvancedHelper (du moteur) était plus tôt dans la chaîne d'appel que le LocalAdvancedHelper (de l'application). En effet, si j'active le débogueur et que je regarde helpers.ancestors, c'est exactement ce qui se passe, ils sont dans l'ordre inverse de ce que je voudrais dans la chaîne des ancêtres. Donc AdvancedHelper (du moteur) pourrait théoriquement appeler 'super' pour appeler LocalAdvancedHelper (de l'application) -- mais cela n'aurait bien sûr pas beaucoup de sens à faire, vous ne voudriez jamais faire cela.
Mais ce que je serait veulent faire... que je ne peux pas faire.
Quelqu'un a-t-il une idée, existe-t-il un moyen de fournir cette conception, qui me semble parfaitement raisonnable, où une application peut sélectivement remplacer une méthode d'aide d'un moteur ?
Quelqu'un peut-il expliquer pourquoi il fonctionne de cette façon ? J'ai essayé de regarder le code source de Rails, mais je me suis perdu assez vite, le code autour de ce truc est terriblement abstrait et divisé en plusieurs endroits.
C'est une question assez ésotérique, je ne pense pas que quelqu'un aura une idée, j'espère que vous me surprendrez !
\== Mise à jour
Bon, afin de comprendre quelle partie du code Rails est appelée et à quel endroit, je mets un "def self.included ; debugger ; end" sur chacune de mes aides, puis dans le débogueur je peux lever une exception pour voir une trace de pile.
Cela ne m'aide toujours pas vraiment à aller au fond des choses, le code Rails saute partout et est assez confus.
Mais il est clair qu'une aide portant le nom "standard" (par exemple WidgetHelper pour WidgetController) est appelée par un code rails différent, pour être incluse dans le module d'aide de vue "maître" pour un contrôleur donné, que les autres aides. Je me demande si je donne un nom différent à l'aide, puis l'inclus manuellement dans mon contrôleur avec ("helper OtherNamedAdvancedHelper"), si cela changera l'ordre de chargement.