Haz que el bundler use diferentes gems para diferentes plataformas

Estoy trabajando en la actualización de una de nuestras aplicaciones Rails 2.3.8 a Rails 3, y me he encontrado con un problema molesto con bundler e implementación. Desarrollo la aplicación en una máquina con Windows, pero el entorno de producción ejecuta Ubuntu Linux. Ahora, mi problema es que bundler está ignorando la gem mysql en el entorno de producción, y Passenger escupe: “¡Falta la gem mysql. Agrégala a tu Gemfile: gem ‘mysql’, ‘2.8.1’”

Aquí está mi Gemfile :

 # Edit this Gemfile to bundle your application's dependencies. # This preamble is the current preamble for Rails 3 apps; edit as needed. source 'http://rubygems.org' gem 'rails', '3.0.0' gem 'net-ldap', :require => 'net/ldap' gem 'highline', :require => 'highline/import' gem 'mysql', '2.8.1' gem 'net-ssh', :require => 'net/ssh' # Bundle gems for the local environment. Make sure to # put test-only gems in this group so their generators # and rake tasks are available in development mode: group :development, :test do gem 'fakeweb', :require => 'fakeweb' gem 'flexmock', :require => 'flexmock/test_unit' end 

Como puede ver, se especifica la gem mysql . Sin embargo, al implementar, bundler lo ignora. ¿Por qué? El motivo es que Bundler genera el siguiente Gemfile.lock (solo se incluyen las piezas relevantes):

 .... mime-types (1.16) mysql (2.8.1-x86-mingw32) net-ldap (0.1.1) .... 

Tenga en cuenta que incluye la gem específica de la plataforma. Esto obviamente NO es lo que quiero que haga, ya que esa joya no es adecuada (y aparentemente ignorada) cuando se ejecuta bajo Linux.

Entonces, ¿Bundler viene con alguna forma de lidiar con estos problemas? ¿O debo recordar cambiar manualmente la versión de la gem mysql en Gemfile.lock generado cada vez que ejecuto bundle install en mi máquina de desarrollo?

¡Gracias de antemano!

Actualizar

Parece que el equipo de bundler es consciente de este problema .

Este es un problema conocido en Bundler . Las soluciones son:

  • Genere un Gemfile.lock en un sistema lo suficientemente similar a su entorno de producción para que obtenga resultados que coincidan con su plataforma de producción. Efectivamente, eso significa que solo puede generar el archivo Gemfile.lock en Windows si su sistema de producción es Windows.
  • No confíe ningún archivo Gemfile.lock y determine las dependencias en la máquina de producción en el momento de la implementación ( bundle install sin --deploy ). Aunque no se recomienda en general, esta es una solución alternativa de uso frecuente hasta que se solucione el error. Por ejemplo, esta es la solución recomendada que ofrece Heroku.
  • Cambie a JRuby, que tendría la misma cadena de plataforma tanto en Windows como en Linux ( java ). No lo recomiendo en serio, pero creo que solucionaría el problema.
  • Solucione el problema en el código fuente de Bundler, es decir, ayude al equipo de Bundler a solucionar el error. 🙂

Tengo un problema similar. Me gustaría poder escribir algo como esto en mi Gemfile:

 platforms :ruby do # linux gem 'nokogiri', "1.5.0.beta.2" end platforms :mswin do gem 'nokogiri', "1.4.4.1" end 

Pero, bundler me dice que no estoy permitido. Entonces, mi solución, que funciona en este caso específico es señalar una gama de versiones:

 gem 'nokogiri', ">= 1.4.4.1", "< =1.5.0.beta.2" 

Que - por el momento - dar la versión 1.4.4.1 en mi computadora con Windows y 1.5.0.beta.2 en mi computadora Linux. Tal vez sea posible que escribas una solución similar y fea 😉

Nuestros ingenieros de Engine Yard han enviado un parche a Bundler para solucionar este problema y descongelar las gems si se encuentran en una plataforma diferente. Hemos tenido el mismo problema con muchos Windows que intentan implementar después de ejecutar el tutorial de demostración de RailsInstaller. La mejor solución que hemos encontrado es realizar lo siguiente:

  1. bundle install como normal en su máquina de desarrollo
  2. Pase por Gemfile.lock y si hay alguna línea con -x86-mingw32 , elimine esa parte.
    • bcrypt-ruby (3.0.1-x86-mingw32) pasa a ser bcrypt-ruby (3.0.1)
  3. Agrega ruby bajo la sección ‘Plataformas’ en Gemfile.lock
  4. Asegúrese de especificar explícitamente la gem necesaria en el Gemfile con la bandera de la plataforma. (No estoy seguro si esto es necesario pero no duele)
    • En Gemfile : `gem ‘bcrypt-ruby’, ‘~> 3.0’,: plataforma => ‘ruby’
  5. bundle install nuevamente que mantendrá la línea bcrypt-ruby (3.0.1) y agregará bcrypt-ruby (3.0.1-x86-mingw32) nuevamente.

Si tiene curiosidad acerca del parche de Bundler, puede recibir notificaciones en https://github.com/carlhuda/bundler/pull/1451.

Espero que esto ayude a cualquiera que todavía esté buscando respuestas.

Creo que el problema es que la gem mysql no descubre correctamente los encabezados necesarios. Puedes arreglar esto yendo a usar la gem mysql2 , solo tendrás que actualizar tus adaptadores de database.yml de database.yml en database.yml para la integración de ActiveRecord.

Además, puede pasar indicadores de comstackción a C que extienden gems si es absolutamente necesario:

bundle config build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config .

Me encontré con este problema antes, y el uso de la gem mysql2 soluciona el problema. Sé que esa no es la respuesta que estás buscando, sino que combinas eso con la respuesta de Diego y estás satisfecho.

¿Has probado usar rvm ( enlace aquí )? Puede instalar Máquinas Virtuales y Gemsets de Ruby aisladas, para que pueda trabajar con un entorno más parecido al que tiene en producción. Honestamente, no sé si resolverá tus problemas, pero vale la pena intentarlo.

De todos modos, sé que esta no es la respuesta que desea escuchar, pero en mi humilde opinión, Windows no es el mejor uso de plataforma cuando se desarrolla en Rails. Recientemente compré una MacBook principalmente para desarrollar aplicaciones de Rails, que te evita muchos dolores de cabeza. También puede instalar Linux en su máquina de desarrollo y usarlo, es mucho mejor que usar puertos de Windows o Cygwin.

No Gemfile.lock y sus gems a la producción. Tienes que ejecutar la bundler install nuevamente en producción.

Puedes hacer algo como esto:

 platforms :ruby do gem "sqlite3-ruby", :require => "sqlite3", :group => [:development, :test] end platforms :jruby do gem 'activerecord-jdbc-adapter', :require => false gem "jdbc-sqlite3", :require => false end 

Por cierto, debes poner tu Gemfile.lock en el control de versiones porque de esta forma todas las máquinas ejecutarán la aplicación con las mismas versiones gems.

Me encontré con este problema y luego terminé escribiendo guión para esta dolorosa tarea. http://gouravtiwari.blogspot.com/2011/03/development-on-windows-deploying-to.html