#282 Upgrading to Rails 3.1
Ya ha salido por fin Rails 3.1. Podemos leer un repaso de sus nuevas funcionalidades en las Notas de Lanzamiento en el sitio RailsGuides, algunas de las cuales ya han sido estudiadas en Railscasts y aquí mismo. En este episodio nos centraremos en el proceso de actualización de una aplicación Rails 3.0 a la versión 3.1, y a modo de ejemplo veremos cómo se ha migrado el sitio Railscasts.
Preparativos
Antes de acometer la actualización a Rails 3.1 tenemos que dar algunos pasos previos. Si el sitio no está funcionando en la última versión de Rails 3.0 (a día de hoy es la 3.0.10) tendremos que actualizarlo. Esto lo podemos hacer escribiendo la versión en el Gemfile y luego ejecutando bundle
.
gem "rails", "3.0.10"
Lo siguiente que haremos es pasar la batería de tests de la aplicación para comprobar que todos siguen pasando y que no aparecen mensajes de aviso de fin de soporte. Si los hubiera tendremos que corregirlos antes de continuar. En el caso del código de Railscasts no hay estos problemas así que continuaremos con la actualización.
Actualización
Ya estamos listos para empezar con la actualización, que haremos dentro de una nueva rama Git llamada rails31
.
$ git checkout -b rails31
La actualización a Rails 3.1 es muy sencilla, sólo tenemos que ir al Gemfile
de nuestra aplicación y cambiar la versión a la última versión de 3.1 (que ahora mismo es la 3.1.0.
).
gem "rails", "3.1.0"
Ahora ya podemos ejecutar bundle update
para instalar la nueva versión. El próximo cambio que tenemos que hacer es en el fichero de configuración development.rb
donde tenemos que quitar o comentar la siguiente línea:
# config.action_view.debug_rjs = true
Si lanzamos ahora los tests veremos que siguen pasando. Podemos incluso arrancar el servidor Rails y cargar la aplicación en el navegador.
Cambios en la aplicación para usar el conducto de estáticos
El conducto de estáticos es una de las funcionalidades más importantes en Rails 3.1 pero por ahora nuestra aplicación no lo tiene en cuenta y aloja sus imágenes en el directorio /public
. Esta funcionalidad es totalmente opcional y no tiene ningún efecto hasta que la activemos por lo que si no podemos o queremos usar el conducto de estáticos no tenemos por qué quedarnos sin migrar a Rails 3.1.
Si nos interesa usar el conducto de estáticos debemos añadir las siguientes líneas al Gemfile
(son las que se generarían automáticamente si empezásemos con una aplicación Rails 3.1 desde cero).
# Gems used only for assets and not required # in production environments by default. group :assets do gem 'sass-rails', " ~> 3.1.0" gem 'coffee-rails', " ~> 3.1.0" gem 'uglifier' end gem 'jquery-rails'
Este código crea un grupo assets
e instala varias gemas relacionadas con los estáticos. También incluye la gema jquery-rails
para que podamos usar jQuery (los que prefieran usar Prototype pueden usar prototype-rails
). También tenemos que modificar /config/application.rb
, quitando este código:
# If you have a Gemfile, require the gems listed there, including any gems # you've limited to :test, :development, or :production. Bundler.require(:default, Rails.env) if defined?(Bundler)
Y escribiendo este otro:
if defined?(Bundler) # If you precompile assets before deploying to production, use this line Bundler.require *Rails.groups(:assets => %w(development test)) # If you want your assets lazily compiled in production, use this line # Bundler.require(:default, :assets, Rails.env) end
El código añade el grupo assets
a los grupos sobre los que Bundler hará un require
. Aquí se efectúa también la activación propiamente dicha del conducto de estáticos, dentro de la clase Application
:
# Enable the asset pipeline config.assets.enabled = true # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0'
Este código activa el conducto de estáticos y genera un número de versión, que podremos cambiar para expirar los recursos estáticos.
Debemos cambiar también los valores de configuración en el fichero de configuración de cada entorno. Empecemos por development.rb
. Tenemos que hacer aquí un par de cambios para permitir la depuración:
# Do not compress assets config.assets.compress = false # Expands the lines which load the assets config.assets.debug = true
El siguiente es production.rb
.
# Compress JavaScript and CSS config.assets.compress = true # Don't fallback to assets pipeline config.assets.compile = false # Generate digests for assets URLs config.assets.digest = true
En producción nos interesa comprimir los estáticos, pero como éstos irán precompilados pondremos compile
a false
. También estableceremos digest
a true
para que las URLs lleven su propia huella. Estas opciones se pueden configurar de forma diferente para adaptarse al funcionamiento de nuestra aplicación en producción.
Por último modificaremos el entorno de pruebas. Aquí añadiremos opciones de forma que los recursos estáticos se sirvan y guarden en caché:
# Configure static asset server for tests with Cache-Control for performance config.serve_static_assets = true config.static_cache_control = "public, max-age=3600" # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets config.assets.allow_debugging = true
Si utilizamos Git para llevar el control de versiones en nuestra aplicación deberíamos modificar el fichero .gitignore
y añadir el directorio .sass-cache
al listado de elementos ignorados porque no nos interesará guardar en Git la caché de SASS.
.sass-cache/
Cambio de sitio de los estáticos
Ahora que ya tenemos el conducto listo, debemos crear el directorio app/assets
para mover allí los directorios images
, javascripts
y stylesheets
que teníamos en /public
.
$ mkdir app/assets $ mv public/images/ app/assets/ $ mv public/javascripts/ app/assets/ $ mv public/stylesheets/ app/assets/
Algunos de estos archivos ya no hacen falta, como por ejemplo los ficheros jquery.js
, jquery.min.js
y rails.js
del directorio javascripts
que ahora vienen incluidos en la gema jQuery así que los borraremos. También es un buen momento para decididr si queremos mover los plugins de jQuery a lib/assets
o vendor/assets
, como hicimos en el episodio 279 [verlo, leerlo].
A continuación debemos crear los manifiestos. La aplicación ya tiene su application.js
y application.css
en los directorios necesarios, así que no los tenemos que crear. Empezaremos con el fichero CSS. Para convertirlo en un manifiesto tenemos que añadir algunos comentarios en la parte superior para indicarle a Sprockets los ficheros que debe incluir. Nosotros le diremos que incluya el resto del fichero y el resto de archivos que residan en el directorio stylesheets
y sus subdirectorios.
/* *= require_self *= require_tree . */ /* rest of file omitted */
Podemos hacer lo mismo en el fichero application.js
, pero para incluir jQuery tenemos que hacerlo de forma un poco diferente:
//= require jquery //= require jquery_ujs //= require_self //= require_tree . /* rest of file omitted */
De nuevo haremos require_self
porque el propio fichero contendrá su código y también require_tree
para incluir el resto de los ficheros del directorio.
También tenemos que ir al fichero layout y cambiar las líneas que incluyen las hojas de estilo y los ficheros de JavaScript de forma que sólo hagan referencia al fichero relevante, porque los otros los incluirá el manifiesto.
<%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", "http://cdn.sublimevideo.net/js/3s7oes9q.js" %>
Nuestro JavaScript necesita incluir un fichero externo que no se encontrará en el conducto de estáticos por lo que debemos seguir incluyéndolo en la primera línea.
Ya podemos probar la aplicación en el navegador para ver si nuestros cambios funcionan, pero antes debemos ejecutar bundle
para instalar todas las gemas necesarias. Tras esto podemos arrancar el servidor.
$ rails s
Funciona casi todo pero quedan algunas imágenes rotas, por ejemplo el logo en la parte superior.
El problema es que la URL de la imagen ha sido escrita a fuego en el fichero de layout.
<img src="/images/railscasts_logo.png" width="423" height="56" alt="RailsCasts = Ruby on Rails Screencasts"/>
Esto no funciona porque las imágenes de nuestra aplicación ya no se alojan en /public/images
. La solución más sencilla sería cambiar la URL por /assets/railscasts_logo.png
pero tendremos problemas en producción. Si tenemos la opción assets.digest
se añadirá una huella al final del nombre de forma que no nos bastará con tener una referencia estática a este fichero. Deberíamos siempre utilizar los métodos helper para enlazar correctamente la imagen en desarrollo y producción:
<%= image_tag("railscasts_logo.png", :size => "423x56", :alt => "RailsCasts - Ruby on Rails Screencasts") %>
Tenemos que buscar globalmente en nuestra aplicación y cambiar todos los estáticos que estén referenciados a mano para pasar a usar los helpers de Rails como con la imagen anterior. Si ahora recargamos la página y vemos el logo esto querrá decir que el conducto de estáticos funciona correctamente.
Con esto hemos terminado la actualización a Rails 3.1 de nuestra aplicación. Hay otras funcionalidades extra de las que nos podemos aprovechar y que se pueden consultar en el resto de episodios dedicados a Rails 3.1 por si nos fueran de utilidad en nuestras aplicaciones.