Un courriel que j’ai reçu récemment…. Cher Jean-Marc, J’ai un plugin que je viens de développer et que j’aimerais réutiliser dans une nouvelle application. Mon problème est que la nouvelle application doit être en plusieurs langues alors que mon plugin ne fonctionne qu’en une seule langue. Je sais que je pourrais changer le plugin mais j’devrais aussi
modifier les applications qui l’utilisent déjà. T’as une recommandation pour résoudre mon problème? Pris-entre Deuxfeux ——————————————————- Cher Pris-entre, La solution à ton problème est au cœur même du langage Ruby. Le langage est dynamique même au niveau des classes et modules.
Supposons que tu ai un plugin du nom de « mon_plugin »… et que la classe qui t’intéresse s’appelle « ProfileUtilisateur » (donc dans un fichier nommé « profile_utilisateur.rb » sous le répertoire « models »). Finalement, supposons que tu utilises Globalize pour rendre ton application multilingue et que les colonnes à traduire sont le nom et la description. Si tu créé un fichier avec le même nom que la classé à étendre dans le répertoire « models » de ton application tu vas cacher le fichier original et en perdre la fonctionnalité. Pourtant cette approche est très proche de la solution finale. Donc… tu créé le fichier « profile_utilisateur.rb » dans ton répertoire de modèle et tu place le code suivant dans le fichier: extend_plugin_class(:mon_plugin, :models, :profile_utilisateur).class_eval do self.keep_translations_in_model = true self.translates :nom, :description, :base_as_default => true end La méthode « extend_plugin_class » retourne la classe que l’on cherche à étendre… mais la technique à utiliser est déjà là avec la méthode « class_eval ». Cette dernière permet d’altérer le code déjà en mémoire de la classe. C’est donc ainsi que l’on peut utiliser les méthodes de Globalize pour indiquer que la classe doit être traduite dans cette application. Reste donc à comprendre comment la méthode « extend_plugin_class » fonctionne… en voici le code: def extend_plugin_class(plugin_name, class_type, class_name, &block) plugin_location = « /../vendor/plugins/%s/app/%s/%s.rb »%[plugin_name, class_type, class_name] require File.expand_path(File.dirname(RAILS_ROOT) + plugin_location) class_name.to_s.classify.constantize end
On sait que Ruby on Rails favorise la normalisation à la configuration. Donc, l’emplacement des fichiers de classes d’un plugin seront nécessairement à l’endroit attendu. Trois étapes très simples, déterminer le nom du fichier à charger, le charger en mémoire et retourner la classe à étendre. Simple, bref, mais très efficace… enfin j’espère que ça répond à ta question. Bonne chance!
Jean-Marc