2012-03-19 17 views
43

TL; DRrbenv: Sobrevivir sin gemsets

  • No se moleste con gemsets; múltiples versiones de una gema pueden ser instaladas concurrentemente.
  • Cuando sea necesario, especifique qué versión ejecutar con la notación $ gem-based-binary _version_ args.
  • Use bundle exec cuando tenga un Gemfile que especifica la versión.
gem install rails -v 3.2.13 
rails _3.2.13_ new Project2 
cd Project2 
bundle exec rails server 

ACTUALIZACIÓN: 2015-06-04

escribí esta pregunta hace tres años. En parte, se basaba en una suposición falsa, y en parte la situación ha cambiado desde entonces. Con el agradecimiento de @indirect por su respuesta original, quiero llamar la atención sobre la respuesta más reciente (menos votada) de @ kelvin, resumida anteriormente.

Mi suposición errónea: Solo se podía instalar una única versión de una gema a la vez, de ahí la necesidad de que las gemas aislaran el espacio de nombres. No es verdad. Se pueden instalar varias versiones de una gema al mismo tiempo. El más reciente se usará cuando se invoque desde una línea de comando, a menos que tenga un Gemfile que especifique las restricciones de versión e invoque el comando a través de bundle exec, o especifique la versión como su primer argumento.

Véase también How can I call an older version of a gem from the commandline? re: la notación de la versión de subrayado.


pregunta original:

tengo varios proyectos en marcha sobre el uso de diferentes versiones de los carriles. Tengo un flujo de trabajo (descrito a continuación) para crear proyectos utilizando versiones específicas de rieles y mantener los proyectos aislados el uno del otro. Me gustaría experimentar con otros flujos de trabajo, en particular, utilizando rbenv en lugar de RVM, pero no está claro cómo hacerlo.

PREGUNTA: Cuál es el las mejores prácticas actuales para la creación de múltiples proyectos de carriles, cada uno usando una versión diferente de los carriles, al hacer uso de rbenv y bundler, en contraposición a rbenv-gemset o RVM ?

USE CASE: Tengo dos proyectos de rieles, llamados ProjectA y ProjectB. ProjectA se desarrolla utilizando una versión de rieles ("RailsA"), mientras que ProjectB usa una versión diferente ("RailsB"). ¿Cómo logro tener ambas versiones instaladas?

EL ENFOQUE GEMSETS: Cuando comencé con el desarrollo de Rails, utilicé RVM. Además de admitir instalaciones simultáneas múltiples de ruby, RVM admite tener múltiples Named Gem Sets.Cada proyecto tiene su propia colección independiente de gemas (incluida la propia rieles) llama un gemset:

rvm gemset create RailsA 
rvm gemset use RailsA 
# RailsA. Note: My question is not version-specific. 
gem install rails --version 3.0 
rails new ProjectA 
cd ProjectA 
rvm --rvmrc use `rvm current` 
vi Gemfile 
bundle install 
cd .. 
## Now do the same for ProjectB 
rvm gemset create RailsB 
rvm gemset use RailsB 
gem install rails --version 3.2 
rails new ProjectB 
cd ProjectB 
rvm --rvmrc use `rvm current` 
vi Gemfile 
bundle install 

Nota: El mismo creación de las carpetas del proyecto debe hacerse (en mi humilde opinión) por un comando rails new utilizando el desear versión de rieles, ya que los archivos esqueleto cambian de una versión a otra. (Tal vez debería volver a esta premisa?)

ENFOQUE bundler: He estado jugando con el uso de rbenv en lugar de RVM, pero no comprender el flujo de trabajo de la forma más clara. En el README.md, Sam Stephenson escribe que "rbenv no ... administra conjuntos de gemas. Bundler es una forma mejor de administrar dependencias de aplicaciones". Hay un complemento (rbenv-gemset) para obtener los mismos resultados que las gemas de rvm, pero Sam claramente prefiere utilizar Bundler. Desafortunadamente, no explica en detalle cómo sería el flujo de trabajo. Incluso el sitio web Bundler no conecta explícitamente todos los puntos de cómo aislar un proyecto de otro. Varios blogsandgists vienen al rescate, lo que sugiere la ~/.bundle/config siguiente archivo:

--- 
BUNDLE_PATH: vendor/bundle 

(Por cierto, no estoy seguro de lo que el "---" es acerca de los documentos no hacen mención de ella y que doesn. parece hacer una diferencia.)

Esto da a cada proyecto de rieles su propio gemset, almacenando las gemas en ProjectX/vendor/bundle /. De hecho, los rieles se reinstalarán allí, haciendo que el proyecto sea completamente independiente del resto de mi entorno, una vez que ejecuto bundle install.

Pero el elefante en la habitación es el problema de la gallina y el huevo de la creación de la carpeta del proyecto rieles en el primer lugar !! Para crear la carpeta ProjectA usando RailsA, necesito instalar los rieles (y sus numerosas dependencias) primero. Pero cuando quiero crear ProjectB, debo pasar a utilizar RailsB. Sin gemas, debo hacer una actualización/degradación seria. No genial.

Una posible solución es simplemente no preocuparse por la versión de los rieles que uso para crear la carpeta ProjectX. Si luego uso Rails 3.0 para crear un proyecto 3.2, podría simplemente crear manualmente el árbol de aplicaciones/activos. Pero eso solo me molesta. ¿No hay una mejor manera?

+2

Parece que REALMENTE quiere usar RVM y gemas. ¿Alguna razón particular por la que elige NO utilizar la herramienta que resuelve su problema de la manera más elegante? –

+4

No estoy comprometido con ninguna herramienta en particular (y absolutamente no quiero entrar en una discusión "RVM vs rbenv"). Estoy más familiarizado con RVM y entiendo un flujo de trabajo para usarlo. Me gustaría entender el flujo de trabajo equivalente para rbenv, si acaso solo para tener fluidez con una variedad de herramientas. –

+1

Usted dice que el sitio web de Bundler no explica cómo "aislar un proyecto de otro". Si "aislar" significa que cada proyecto tiene una copia separada de la misma gema y versión (por ejemplo, rack-1.4.0), Bundler no lo hace. Mantiene una copia única de cada joya en el disco, y cualquier aplicación que necesite esa joya y versión puede usarla sin interferir con otras aplicaciones.Es como ejecutar 2 instancias de 'bash'; no tienes múltiples copias de 'bash' en el disco, sino múltiples copias en la memoria. Los conjuntos de genes le permiten tener múltiples copias en el disco (que pueden ser más fáciles de eliminar cuando ya no son necesarias) – Kelvin

Respuesta

12

Supongamos que tiene los rieles 3.1.0 instalados, pero desea crear un nuevo proyecto utilizando los rieles 3.2.13 que no está instalado.

Digamos que desea que el nuevo proyecto esté en ~/projects/Project2.

gem install rails -v 3.2.13 
cd ~/projects 
rails _3.2.13_ new Project2 

Esto creará el Gemfile para usted, bloqueado en la versión de los carriles que ha especificado en la línea de comandos.

Omití deliberadamente la idea de guardar una copia separada de las gemas para el nuevo proyecto, porque eso va en contra de la filosofía de Bundler, que es tener todas las gemas instaladas en un solo lugar. Cuando ejecuta raíles, Bundler seleccionará automáticamente las versiones de gemas correctas desde esa ubicación central. Eso significa que un proyecto puede compartir gemas en lugar de instalar una copia nueva para sí mismo. (Sin embargo, tenga en cuenta que cada versión de Ruby que instale tendrá sus propias gemas. Esto es bueno porque las extensiones nativas probablemente no funcionen en las versiones ruby.)

Tiene que ser un poco más consciente, porque la mayoría de los comandos, como rake, cargarán la versión más reciente de rake que haya instalado. Tendrá que ejecutar bundle exec rake ... para asegurarse de que se cargue la versión correcta. Por lo general, ejecutaré bundle exec para todos los comandos excepto rails. Puede crear un alias para hacerlo más corto (yo uso bex). Para automatizar esto con ejecutables gema, puede usar rbenv-binstubs, pero aún debe tener en cuenta que ejecutar ejecutables que no sean gem como ruby y irb no usará automáticamente el Gemfile.

Nota al margen: rails new se ejecutará bundle install, que comprobará para la versión más reciente de las dependencias. Si desea que el paquete intente utilizar gemas instaladas actualmente que satisfagan los requisitos de dependencia, puede omitir el bundle install con rails new --skip-bundle, luego ejecutar bundle check en el directorio de la aplicación.

Sidenote 2: supongamos que desea utilizar una versión ruby ​​para Project2 (por ejemplo, 2.1.8) que es diferente de la predeterminada (por ejemplo, 2.3.0). En ese caso, ejecutar gem install como se especifica arriba instalará las gemas en 2.3.0, lo cual es una pérdida de tiempo porque tendrá que instalar las gemas de nuevo en 2.1.8. Para resolver ese problema, puede forzar a los comandos para utilizar la versión preferida a través de la variable de entorno:

RBENV_VERSION=2.1.8 gem install rails -v 3.2.13 
cd ~/projects 
RBENV_VERSION=2.1.8 rails _3.2.13_ new Project2 
echo 2.1.8 > Project2/.ruby-version 

Usted podía uso rbenv shell para establecer la variable, pero solo recomiendo que si usted no quiere a rbenv auto-switch basado en archivos .ruby-version durante la duración de ese shell. Es muy fácil olvidar que tiene la variable configurada, y cuando cede a un proyecto diferente, no usará la versión que espera.

+0

re: Sidenote 2 : Creo que podría olvidar el nombre de la variable y buscarlo. No vale la pena el tiempo. Es mejor abrir una nueva ventana para una sesión rápida de 'rbenv shell', que se cierra inmediatamente después. Personalmente, eso sería más fácil para mí recordar. YMMV. Además, si usa 'bundle exec' para _todos los comandos, _including_' rails', Bundler lo atraparía si olvidara que había ejecutado 'rbenv shell' y se fue a otra carpeta del proyecto. –

+0

¿Cuál es su razonamiento para no iniciar Rails con Bundler? (re: "Usualmente ejecutaré bundle exec para todos los comandos, excepto los raíles") –

+0

n.b. algunos alias a los que soy adicto: alias be = 'bundle exec'; alias brs = 'Ser servidor de rails'; alias brc = 'ser la consola de los rails'; –

42

La mayoría de las personas resuelve esto instalando la gema de los rieles primero a través de gem install rails. Si se niega a hacerlo por algún motivo, puede optar por excluirse de la agrupación automática que Rails intenta hacer por usted. Esto funcionará completamente independientemente de su sistema de administración de ruby.

mkdir myapp 
cd myapp 
echo "source :rubygems" > Gemfile 
echo "gem 'rails', '3.2.2'" >> Gemfile 
bundle install --path vendor/bundle 
bundle exec rails new . --skip-bundle 

Cuando se le solicite, escriba "y" para reemplazar su Gemfile con los rieles que viene por defecto (o no, como usted prefiera). Entonces, una vez que se hace:

bundle install 

haya terminado, y que han boostrapped una nueva aplicación rieles con la versión de su elección sin necesidad de instalar la gema carriles en rubygems.

+3

No relacionado con esta solución, pero nunca edite su archivo .bundle/config. Si desea aislar las gemas de un proyecto, use 'bundle install --path vendor/bundle'. – indirect

+0

¡Gracias, indirecto! ¿Podría explicar su comentario? ¿Qué pasa con el enfoque ~/.bundle/config? ¿Por qué es mejor usar --path? –

+0

Y mientras estamos en el tema de ~/.bundle/config, ¿qué hace el triple-dash? –

8

Hay una buena publicación reciente sobre exactamente el tema de gemsets/bundler aquí http://rakeroutes.com/blog/how-to-use-bundler-instead-of-rvm-gemsets/ Buen fondo que puede aplicar a su configuración de rbenv.

+0

Muy buena redacción. Si hubiera sabido eso, no habría tenido que publicar [mío] (http://www.relativkreativ.at/articles/managing-multiple-rails-versions-with-rbenv) :-) –

Cuestiones relacionadas