Noté que al crear un plugin, si añado una carpeta lib y algunos archivos en ella, puedo usar require porque se agrega a la $LOAD_PATH.
Por ejemplo, el plugin docker_manager tiene un archivo lib/docker_manager/git_repo.rb. Al ejecutar la consola de Rails con rails c, puedo escribir require 'docker_manager/git_repo'.
Me pregunto cómo Discourse hace que todas estas rutas estén disponibles.
Noté que en el archivo /lib/plugin/instance.rb, si comento la línea 671: self.instance_eval File.read(path), path, entonces require deja de funcionar. Sin embargo, no entiendo cómo instance_eval podría agregar directorios a la load_path.
Muchos archivos plugin.rb inicializan un Rails Engine, lo cual añade varias cosas al path de carga.
Cuando no tenemos un Rails Engine, verás muchas llamadas a require_relative en la parte superior del archivo plugin.rb para compensar.
Creo que esto se debe a que instance_eval está ejecutando el archivo plugin.rb. Si plugin.rb no se ejecuta, el Rails Engine nunca se crea y las rutas adicionales no se añaden al load_path.
Estaba intentando implementar el mismo sistema de plugins y mi problema era que los estaba activando más tarde, fuera de application.rb, por ejemplo en un initializer. De esa manera, la carpeta lib (y probablemente otras) de los plugins no se añade al path de carga.