Molti plugin includono molte definizioni di classi all’interno di plugin.rb, o utilizzano require_relative per caricare file ruby. Questo funziona, ma presenta alcuni svantaggi:
- Nessun ricaricamento automatico delle modifiche in fase di sviluppo. Qualsiasi modifica richiede un riavvio completo del server
- Ottenere le chiamate
requirenell’ordine corretto può essere complicato - Se vengono caricate (
required) al di fuori del bloccoafter_initialize, altre classi/moduli caricati automaticamente potrebbero non essere disponibili
Esiste una soluzione! I plugin possono sfruttare il sistema di caricamento automatico standard di Rails. Per i nuovi plugin, tutto ciò di cui hai bisogno è definito nel plugin-skeleton. Questo argomento descrive come adattare un plugin esistente ed estendere la configurazione.
1. Definire un modulo e un Rails::Engine per il tuo plugin
In plugin.rb, definisci un modulo per il tuo plugin con un PLUGIN_NAME univoco e aggiungi una riga require_relative per caricare il file engine che stiamo per creare.
# name: my-plugin-name
# ...
module ::MyPluginModule
PLUGIN_NAME = "my-plugin-name"
end
require_relative "lib/my_plugin_module/engine"
Ora crea {plugin}/lib/my_plugin_module/engine.rb:
module ::MyPluginModule
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace MyPluginModule
end
end
Cose importanti da notare:
-
In plugin.rb, devi includere
::prima del nome del tuo modulo per definirlo nello spazio dei nomi principale (altrimenti, verrebbe definito sottoPlugin::Instance) -
require_relative "lib/.../engine"deve trovarsi nella radice del fileplugin.rb, non all’interno di un bloccoafter_initialize -
Mettere l’engine nel suo file separato sotto
lib/è importante. Definirlo direttamente nel fileplugin.rbnon funzionerà. (Rails utilizza la presenza di una directorylib/per determinare la radice dell’engine) -
Il percorso del file deve includere il nome del modulo, secondo le regole di Zeitwerk
-
engine_nameviene utilizzato come prefisso per i task rake e qualsiasi route definita dall’engine (
docs rails) -
isolate_namespaceaiuta a prevenire perdite tra il core e il plugin (
docs Rails)
2. Definire file ruby nella corretta struttura di directory
L’engine caricherà automaticamente tutti i file in {plugin}/app/{type}/*. Ad esempio, possiamo definire un controller
{plugin}/app/controllers/my_plugin_module/examples_controller.rb
module ::MyPluginModule
class ExamplesController < ::ApplicationController
requires_plugin PLUGIN_NAME
def index
render json: { hello: "world" }
end
end
end
Questo verrà ora caricato automaticamente ogni volta che qualcosa in Rails tenterà di accedere a ::MyPluginModule::MyController. Per testare, prova ad accedere a quella classe dalla console rails.
Affinché il caricamento automatico funzioni correttamente, i percorsi dei file devono corrispondere alla gerarchia completa di moduli/classi secondo le regole definite da Zeitwerk.
3. Definire route sull’engine del plugin
Crea un file {plugin}/config/routes.rb
MyPluginModule::Engine.routes.draw do
get "/examples" => "examples#index"
# definisci qui le route
end
Discourse::Application.routes.draw do
mount ::MyPluginModule::Engine, at: "my-plugin"
end
Questo file verrà caricato automaticamente dall’engine e le modifiche avranno effetto senza riavvio del server. In questo caso, l’azione del controller sarà disponibile su /my-plugin/examples.json.
4. Aggiungere altri percorsi caricabili automaticamente
A volte potresti voler introdurre directory aggiuntive di file Ruby caricabili automaticamente. L’esempio più comune è la directory lib/ in un plugin.
Modifica la definizione del tuo engine per aggiungere lib/ ai percorsi di caricamento automatico dell’engine:
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace MyPluginModule
config.autoload_paths << File.join(config.root, "lib")
end
Ora puoi definire un modulo lib come
{plugin}/lib/my_plugin_module/some_lib_module.rb
module ::MyPluginModule::SomeLibModule
end
E ora qualsiasi riferimento a ::MyPluginModule::SomeLibModule caricherà automaticamente il modulo da questo file.
5. Profitto!
Tutti questi file verranno ora caricati automaticamente senza chiamate require deliberate. Le modifiche verranno raccolte automaticamente da rails e ricaricate in loco senza riavvio del server.
Questo documento è controllato in versione - suggerisci modifiche su github.