2011-12-13 23 views
9

Tengo la aplicación Rails 3.0.x. Me gustaría cargar gemas en tiempo de ejecución, sin usar Gemfile.Cargando gema en tiempo de ejecución en Rails 3

Lo que me gustaría lograr es cargar mi aplicación como de costumbre, con las gemas regulares cargadas por Bundler. Después de eso, me gustaría cargar todas las gemas (Rails Engines) ubicadas en un directorio específico (pero hasta el tiempo de ejecución, no sé qué gemas serán).

¿Alguien sabe si esto es posible en Rails, quizás usando Bundler API?

+0

Por curiosidad: ¿podría explicar el uso de los casos? No me queda claro por qué querrías hacer esto. – nathanvda

+0

La idea era tener una aplicación modular Rails que cargara sus módulos en tiempo de ejecución. Quería poner módulos/gemas en el directorio, iniciar la aplicación y ser flexible :) –

+0

Bien, supongo que tiene alguna aplicación genérica de rieles que instala en el sitio del cliente, y en función de algunas opciones (tarifa/licencia), instale los módulos correctos en la carpeta. Pero, ¿qué sucede si solo edita el Gemfile y agrupa la instalación? Es menos trabajo, es más seguro, y la única edición/configuración fue la edición de Gemfile. Esto es lo que hacemos. Recibimos nuestro propio gemserver para nuestras gemas "privadas". Si un módulo está habilitado o deshabilitado, solo editamos el Gemfile, el paquete y reiniciamos. – nathanvda

Respuesta

6

Lo que estamos tratando de hacer es peligroso. Si cada uno de tus Rails Engines también son gemas, entonces también tendrían Gemfiles con otras dependencias, y esas a su vez tendrían otras dependencias, etc. Si permites que Bundler las resuelva, entonces tendrás menos problemas en el tiempo de ejecución.

Así es como lo haría sin ningún tipo de hacks. Recuerde que su Gemfile es solo código Ruby, y puede tener gemas que no están cargadas de forma predeterminada.

# In your Gemfile, add at the end: 
Dir[YOUR_RAILS_ENGINES_SUBFOLDER + "/*/*.gemspec"].each do |gemspec_file| 
    dir_name = File.dirname(gemspec_file) 
    gem_name = File.basename(gemspec_file, File.extname(gemspec_file)) 

    # sometimes "-" and "_" are used interchangeably in gems 
    # for e.g. gemspec_file is "engines/my-engine/my_engine.gemspec" 
    # dir_name will be engines/my-engine 
    # gem_name will be my_engine 

    # Register that engine as a dependency, *without* being required 
    gem gem_name, :path => dir_name, :require => false 

    # e.g. this is similar to saying 
    # gem 'my_engine', :path => 'engines/my-engine', :require => false 
end 

Ahora tiene todos los motores dinámicos de Rails registrados como dependencias de gemas. Bundler los resolverá, y todas sus subdependencias, para que no tenga que preocuparse por nada. Simplemente ejecute bundle install una vez antes de ejecutar la aplicación, o cada vez que agregue/elimine cualquier motor en esa carpeta.

Lo bueno es que estas gemas solo se registrarán y no se cargarán. Así que en su código de producción, ahora se puede cargar cualquier joya que elija en tiempo de ejecución simplemente diciendo require <your-engine-name>

Editar: Código adicional comenta

+1

Bien, hice esta pregunta hace 1,5 años y ya no estoy usando Rails, pero creo que esto es lo que estaba buscando y podría funcionar. Gracias –

+1

No soy el OP, pero comencé la recompensa por esta pregunta. La pregunta que se hizo fue cómo cargar dinámicamente los motores en tiempo de ejecución, no al inicio. Si cargar al inicio era suficiente, un enfoque más simple sería llamar a Bundler.load_gemspec desde boot.rb. –

+0

Este código está lejos de cargar las gemas * dinámicamente *. – Nowaker

0

Prueba esto:

Bundler.with_clean_env do 
    # require gems... 
end 
+0

Lo intenté antes y no sé si me falta algo, pero si agrego esta línea a 'boot.rb' obtengo un error:' 'my_gem' no es parte del paquete. Agrégalo a Gemfile. –

+0

¿Qué quieres decir con escribir: '# require gems ...', quizás esto es lo que me falta? –

Cuestiones relacionadas