De nombreux plugins incluent de nombreuses définitions de classes dans plugin.rb, ou utilisent require_relative pour charger des fichiers ruby. Cela fonctionne, mais présente certains inconvénients :
- Pas de rechargement automatique des modifications en développement. Toute modification nécessite un redémarrage complet du serveur.
- Obtenir les appels
requiredans le bon ordre peut être pénible. - S’ils sont
requireen dehors du blocafter_initialize, d’autres classes/modules auto-chargés peuvent ne pas être disponibles.
Il existe une solution ! Les plugins peuvent s’appuyer sur le système d’auto-chargement standard de Rails. Pour les nouveaux plugins, tout ce dont vous avez besoin est défini dans le squelette de plugin. Ce sujet décrit comment adapter un plugin existant et étendre la configuration.
1. Définir un module et un Rails::Engine pour votre plugin
Dans plugin.rb, définissez un module pour votre plugin avec un PLUGIN_NAME unique, et ajoutez une ligne require_relative pour charger le fichier moteur que nous allons créer.
# nom : mon-nom-de-plugin
# ...
module ::MonModulePlugin
PLUGIN_NAME = "mon-nom-de-plugin"
end
require_relative "lib/mon_module_plugin/engine"
Créez maintenant {plugin}/lib/mon_module_plugin/engine.rb :
module ::MonModulePlugin
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace MonModulePlugin
end
end
Points importants à noter :
-
Dans
plugin.rb, vous devez inclure::avant le nom de votre module pour le définir dans l’espace de noms racine (sinon, il serait défini sousPlugin::Instance). -
require_relative "lib/.../engine"doit se trouver à la racine du fichierplugin.rb, pas à l’intérieur d’un blocafter_initialize. -
Placer le moteur dans son propre fichier sous
lib/est important. Le définir directement dans le fichierplugin.rbne fonctionnera pas. (Rails utilise la présence d’un répertoirelib/pour déterminer la racine du moteur). -
Le chemin du fichier doit inclure le nom du module, conformément aux règles de Zeitwerk.
-
Le
engine_nameest utilisé comme préfixe pour les tâches rake et toutes les routes définies par le moteur (:lien: docs rails). -
isolate_namespaceaide à éviter les fuites entre le cœur et le plugin (:lien: docs Rails).
2. Définir des fichiers ruby dans la bonne structure de répertoires
Le moteur auto-chargera maintenant tous les fichiers dans {plugin}/app/{type}/*. Par exemple, nous pouvons définir un contrôleur
{plugin}/app/controllers/mon_module_plugin/examples_controller.rb
module ::MonModulePlugin
class ExamplesController < ::ApplicationController
requires_plugin PLUGIN_NAME
def index
render json: { hello: "world" }
end
end
end
Celui-ci sera maintenant auto-chargé chaque fois que quelque chose dans Rails essaiera d’accéder à ::MonModulePlugin::MyController. Pour tester, essayez d’accéder à cette classe depuis la console rails.
Pour que l’auto-chargement fonctionne correctement, les chemins de fichiers doivent correspondre à la hiérarchie complète des modules/classes selon les règles définies par Zeitwerk.
3. Définir des routes sur le moteur du plugin
Créez un fichier {plugin}/config/routes.rb
MonModulePlugin::Engine.routes.draw do
get "/examples" => "examples#index"
# définir les routes ici
end
Discourse::Application.routes.draw do
mount ::MonModulePlugin::Engine, at: "mon-plugin"
end
Ce fichier sera automatiquement chargé par le moteur, et les modifications prendront effet sans redémarrage du serveur. Dans ce cas, l’action du contrôleur serait disponible à /mon-plugin/examples.json.
4. Ajouter d’autres chemins auto-chargés
Parfois, vous pourriez vouloir introduire des répertoires supplémentaires de fichiers Ruby auto-chargés. L’exemple le plus courant est le répertoire lib/ dans un plugin.
Modifiez la définition de votre moteur pour ajouter lib/ aux chemins d’auto-chargement du moteur :
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace MonModulePlugin
config.autoload_paths << File.join(config.root, "lib")
end
Vous pouvez maintenant définir un module lib comme
{plugin}/lib/mon_module_plugin/some_lib_module.rb
module ::MonModulePlugin::SomeLibModule
end
Et maintenant, toute référence à ::MonModulePlugin::SomeLibModule chargera automatiquement le module à partir de ce fichier.
5. Profit !
Tous ces fichiers seront maintenant chargés automatiquement sans aucun appel require délibéré. Les modifications seront automatiquement détectées par rails et rechargées sur place sans redémarrage du serveur.
Ce document est contrôlé par version - suggérez des modifications sur github.