NO LEA ESTE ARCHIVO EN GITHUB, LAS GUÍAS ESTÁN PUBLICADAS EN https://guides.rubyonrails.org.

Actualización de Ruby on Rails

Esta guía proporciona pasos a seguir cuando actualice sus aplicaciones a una versión más reciente de Ruby on Rails. Estos pasos también están disponibles en guías de lanzamiento individuales.


1 Consejos Generales

Antes de intentar actualizar una aplicación existente, debe asegurarse de tener una buena razón para hacerlo. Necesita equilibrar varios factores: la necesidad de nuevas funciones, la dificultad creciente de encontrar soporte para el código antiguo y su tiempo y habilidades disponibles, por nombrar algunos.

1.1 Cobertura de Pruebas

La mejor manera de asegurarse de que su aplicación aún funcione después de la actualización es tener una buena cobertura de pruebas antes de comenzar el proceso. Si no tiene pruebas automatizadas que ejerciten la mayor parte de su aplicación, necesitará dedicar tiempo a ejercitar manualmente todas las partes que hayan cambiado. En el caso de una actualización de Rails, eso significará cada pieza de funcionalidad en la aplicación. Hágase un favor y asegúrese de que su cobertura de pruebas sea buena antes de comenzar una actualización.

1.2 Versiones de Ruby

Rails generalmente se mantiene cerca de la última versión de Ruby lanzada cuando se publica:

  • Rails 7.2 requiere Ruby 3.1.0 o más reciente.
  • Rails 7.0 y 7.1 requieren Ruby 2.7.0 o más reciente.
  • Rails 6 requiere Ruby 2.5.0 o más reciente.
  • Rails 5 requiere Ruby 2.2.2 o más reciente.

Es una buena idea actualizar Ruby y Rails por separado. Actualice primero a la última versión de Ruby que pueda, y luego actualice Rails.

1.3 El Proceso de Actualización

Al cambiar versiones de Rails, es mejor moverse lentamente, una versión menor a la vez, para hacer un buen uso de las advertencias de desaprobación. Los números de versión de Rails están en la forma Mayor.Menor.Parche. Las versiones Mayor y Menor pueden hacer cambios en la API pública, por lo que esto puede causar errores en su aplicación. Las versiones de Parche solo incluyen correcciones de errores y no cambian ninguna API pública.

El proceso debería ser el siguiente:

  1. Escriba pruebas y asegúrese de que pasen.
  2. Pase a la última versión de parche después de su versión actual.
  3. Corrija las pruebas y las características desaprobadas.
  4. Pase a la última versión de parche de la siguiente versión menor.

Repita este proceso hasta alcanzar su versión objetivo de Rails.

1.3.1 Cambiando entre versiones

Para cambiar entre versiones:

  1. Cambie el número de versión de Rails en el Gemfile y ejecute bundle update.
  2. Cambie las versiones de los paquetes JavaScript de Rails en package.json y ejecute bin/rails javascript:install si está ejecutando jsbundling-rails.
  3. Ejecute la tarea de actualización.
  4. Ejecute sus pruebas.

Puede encontrar una lista de todos los gems de Rails lanzados aquí.

1.4 La Tarea de Actualización

Rails proporciona el comando rails app:update. Después de actualizar la versión de Rails en el Gemfile, ejecute este comando. Esto le ayudará con la creación de nuevos archivos y cambios de archivos antiguos en una sesión interactiva.

$ bin/rails app:update
       exist  config
    conflict  config/application.rb
Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh]
       force  config/application.rb
      create  config/initializers/new_framework_defaults_7_2.rb
...

No olvide revisar la diferencia, para ver si hubo algún cambio inesperado.

1.5 Configurar Valores Predeterminados del Framework

La nueva versión de Rails podría tener diferentes valores de configuración predeterminados que la versión anterior. Sin embargo, después de seguir los pasos descritos anteriormente, su aplicación aún se ejecutará con los valores predeterminados de configuración de la versión de Rails anterior. Esto se debe a que el valor de config.load_defaults en config/application.rb aún no se ha cambiado.

Para permitirle actualizar a nuevos valores predeterminados uno por uno, la tarea de actualización ha creado un archivo config/initializers/new_framework_defaults_X.Y.rb (con la versión deseada de Rails en el nombre del archivo). Debe habilitar los nuevos valores de configuración descomentándolos en el archivo; esto se puede hacer gradualmente en varios despliegues. Una vez que su aplicación esté lista para ejecutarse con los nuevos valores predeterminados, puede eliminar este archivo y cambiar el valor de config.load_defaults.

2 Actualización de Rails 7.1 a Rails 7.2

Para obtener más información sobre los cambios realizados en Rails 7.2, consulte las notas de lanzamiento.

2.1 Todas las pruebas ahora respetan la configuración active_job.queue_adapter

Si ha configurado config.active_job.queue_adapter en su archivo config/application.rb o config/environments/test.rb, el adaptador que seleccionó anteriormente no se usaba de manera consistente en todas las pruebas. En algunas pruebas se utilizaba su adaptador, pero en otras se utilizaba el TestAdapter.

En Rails 7.2, todas las pruebas respetarán la configuración de queue_adapter si se proporciona. Esto puede causar errores en las pruebas si había configurado queue_adapter en algo distinto de :test, pero había escrito pruebas de una manera que dependía del TestAdapter.

Si no se proporciona ninguna configuración, se seguirá utilizando el TestAdapter.

3 Actualización de Rails 7.0 a Rails 7.1

Para obtener más información sobre los cambios realizados en Rails 7.1, consulte las notas de lanzamiento.

3.1 Archivo secret_key_base cambiado en entornos de desarrollo y prueba

En los entornos de desarrollo y prueba, el archivo del que Rails lee el secret_key_base se ha renombrado de tmp/development_secret.txt a tmp/local_secret.txt.

Simplemente puede renombrar el archivo anterior a local_secret.txt para continuar usando el mismo secreto, o copiar la clave del archivo anterior al nuevo.

No hacerlo causará que Rails genere una nueva clave secreta en el nuevo archivo tmp/local_secret.txt cuando se cargue la aplicación.

Esto invalidará todas las sesiones/cookies existentes en los entornos de desarrollo y prueba, y también causará que otras firmas derivadas de secret_key_base se rompan, como los archivos adjuntos de Active Storage/Action Text.

La producción y otros entornos no se ven afectados.

3.2 Las rutas autoloaded ya no están en $LOAD_PATH

A partir de Rails 7.1, los directorios gestionados por los autoloaders ya no se agregan a $LOAD_PATH. Esto significa que no será posible cargar sus archivos con una llamada manual a require, lo cual no debería hacerse de todos modos.

Reducir el tamaño de $LOAD_PATH acelera las llamadas a require para aplicaciones que no usan bootsnap, y reduce el tamaño del caché de bootsnap para las demás.

Si desea que estas rutas todavía estén en $LOAD_PATH, puede optar por incluirlas:

config.add_autoload_paths_to_load_path = true

pero desaconsejamos hacerlo, las clases y módulos en las rutas de carga automática están destinadas a ser cargadas automáticamente. Es decir, simplemente refiérase a ellas.

El directorio lib no se ve afectado por este indicador, siempre se agrega a $LOAD_PATH.

3.3 config.autoload_lib y config.autoload_lib_once

Si su aplicación no tiene lib en las rutas de carga automática o de carga automática única, por favor omita esta sección. Puede averiguarlo inspeccionando la salida de

# Imprimir rutas de carga automática.
$ bin/rails runner 'pp Rails.autoloaders.main.dirs'

# Imprimir rutas de carga automática única.
$ bin/rails runner 'pp Rails.autoloaders.once.dirs'

Si su aplicación ya tiene lib en las rutas de carga automática, normalmente hay una configuración en config/application.rb que se ve algo así

# Cargar automáticamente lib, pero no cargarla ansiosamente (quizás pasado por alto).
config.autoload_paths << config.root.join("lib")

o

# Cargar automáticamente y también cargar ansiosamente lib.
config.autoload_paths << config.root.join("lib")
config.eager_load_paths << config.root.join("lib")

o

# Lo mismo, porque todas las rutas de carga ansiosa también se convierten en rutas de carga automática.
config.eager_load_paths << config.root.join("lib")

Eso todavía funciona, pero se recomienda reemplazar esas líneas con el más conciso

config.autoload_lib(ignore: %w(assets tasks))

Por favor, agregue a la lista de ignore cualquier otro subdirectorio de lib que no contenga archivos .rb, o que no deba ser recargado o cargado ansiosamente. Por ejemplo, si su aplicación tiene lib/templates, lib/generators o lib/middleware, agregaría su nombre relativo a lib:

config.autoload_lib(ignore: %w(assets tasks templates generators middleware))

Con esa línea, el código (no ignorado) en lib también se cargará ansiosamente si config.eager_load es true (el valor predeterminado en modo production). Esto es normalmente lo que desea, pero si lib no se agregó a las rutas de carga ansiosa antes y aún lo desea de esa manera, por favor opte por no hacerlo:

Rails.autoloaders.main.do_not_eager_load(config.root.join("lib"))

El método config.autoload_lib_once es el análogo si la aplicación tenía lib en config.autoload_once_paths.

3.4 ActiveStorage::BaseController ya no incluye el concern de streaming

Los controladores de aplicaciones que heredan de ActiveStorage::BaseController y usan streaming para implementar lógica de servicio de archivos personalizada deben incluir explícitamente el módulo ActiveStorage::Streaming.

3.5 MemCacheStore y RedisCacheStore ahora usan agrupación de conexiones por defecto

El gem connection_pool se ha agregado como una dependencia del gem activesupport, y MemCacheStore y RedisCacheStore ahora usan agrupación de conexiones por defecto.

Si no desea usar agrupación de conexiones, configure la opción :pool en false al configurar su almacén de caché:

config.cache_store = :mem_cache_store, "cache.example.com", { pool: false }

Consulte la guía caching with Rails para obtener más información.

3.6 SQLite3Adapter ahora configurado para usarse en un modo estricto de cadenas

El uso de un modo estricto de cadenas deshabilita los literales de cadena entre comillas dobles.

SQLite tiene algunas peculiaridades en torno a los literales de cadena entre comillas dobles. Primero intenta considerar las cadenas entre comillas dobles como nombres de identificadores, pero si no existen, entonces las considera como literales de cadena. Debido a esto, los errores tipográficos pueden pasar desapercibidos. Por ejemplo, es posible crear un índice para una columna no existente. Consulte la documentación de SQLite para obtener más detalles.

Si no desea usar SQLite3Adapter en un modo estricto, puede deshabilitar este comportamiento:

# config/application.rb
config.active_record.sqlite3_adapter_strict_strings_by_default = false

3.7 Soporte para múltiples rutas de vista previa para ActionMailer::Preview

La opción config.action_mailer.preview_path está obsoleta en favor de config.action_mailer.preview_paths. Agregar rutas a esta opción de configuración hará que esas rutas se utilicen en la búsqueda de vistas previas de correo.

config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"

3.8 config.i18n.raise_on_missing_translations = true ahora genera un error en cualquier traducción faltante.

Anteriormente, solo generaba un error cuando se llamaba en una vista o controlador. Ahora generará un error cada vez que I18n.t reciba una clave no reconocida.

# con config.i18n.raise_on_missing_translations = true

# en una vista o controlador:
t("missing.key") # genera un error en 7.0, genera un error en 7.1
I18n.t("missing.key") # no generaba un error en 7.0, genera un error en 7.1

# en cualquier lugar:
I18n.t("missing.key") # no generaba un error en 7.0, genera un error en 7.1

Si no desea este comportamiento, puede configurar config.i18n.raise_on_missing_translations = false:

# con config.i18n.raise_on_missing_translations = false

# en una vista o controlador:
t("missing.key") # no generaba un error en 7.0, no genera un error en 7.1
I18n.t("missing.key") # no generaba un error en 7.0, no genera un error en 7.1

# en cualquier lugar:
I18n.t("missing.key") # no generaba un error en 7.0, no genera un error en 7.1

Alternativamente, puede personalizar el I18n.exception_handler. Consulte la guía i18n para obtener más información.

AbstractController::Translation.raise_on_missing_translations ha sido eliminado. Esta era una API privada, si dependía de ella, debería migrar a config.i18n.raise_on_missing_translations o a un manejador de excepciones personalizado.

3.9 bin/rails test ahora ejecuta la tarea test:prepare

Al ejecutar pruebas a través de bin/rails test, la tarea rake test:prepare se ejecutará antes de que se ejecuten las pruebas. Si ha mejorado la tarea test:prepare, sus mejoras se ejecutarán antes de sus pruebas. tailwindcss-rails, jsbundling-rails y cssbundling-rails mejoran esta tarea, al igual que otros gems de terceros.

Consulte la guía Testing Rails Applications para obtener más información.

Si ejecuta las pruebas de un solo archivo (bin/rails test test/models/user_test.rb), test:prepare no se ejecutará antes de ellas.

3.10 La sintaxis de importación de @rails/ujs se ha modificado

A partir de Rails 7.1, la sintaxis para importar módulos de @rails/ujs se ha modificado. Rails ya no admite la importación directa de un módulo desde @rails/ujs.

Por ejemplo, intentar importar una función de la biblioteca fallará:

import { fileInputSelector } from "@rails/ujs"
// ERROR: export 'fileInputSelector' (importado como 'fileInputSelector') no se encontró en '@rails/ujs' (posibles exportaciones: default)

En Rails 7.1, los usuarios deben importar primero el objeto Rails directamente desde @rails/ujs. Luego, los usuarios pueden importar módulos específicos desde el objeto Rails.

Un ejemplo de importaciones en Rails 7.1 se muestra a continuación:

import Rails from "@rails/ujs"
// Alias del método
const fileInputSelector = Rails.fileInputSelector
// Alternativamente, referenciarlo desde el objeto Rails donde se utiliza
Rails.fileInputSelector(...)

3.11 Rails.logger ahora devuelve una instancia de ActiveSupport::BroadcastLogger

La clase ActiveSupport::BroadcastLogger es un nuevo logger que permite transmitir registros a diferentes destinos (STDOUT, un archivo de registro...) de manera sencilla.

La API para transmitir registros (usando el método ActiveSupport::Logger.broadcast) fue eliminada y anteriormente era privada. Si su aplicación o biblioteca dependía de esta API, necesita realizar los siguientes cambios:

logger = Logger.new("some_file.log")

# Antes

Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))

# Después

Rails.logger.broadcast_to(logger)

Si su aplicación había configurado un logger personalizado, Rails.logger envolverá y hará proxy de todos los métodos a él. No se requieren cambios de su parte para que funcione.

Si necesita acceder a su instancia de logger personalizada, puede hacerlo utilizando el método broadcasts:

# config/application.rb
config.logger = MyLogger.new

# En cualquier lugar de su aplicación
puts Rails.logger.class #=> BroadcastLogger
puts Rails.logger.broadcasts #=> [MyLogger]

3.12 Cambios en el algoritmo de cifrado de Active Record

El cifrado de Active Record ahora utiliza SHA-256 como su algoritmo de hash digest. Si tiene datos cifrados con versiones anteriores de Rails, hay dos escenarios a considerar:

  1. Si tiene config.active_support.key_generator_hash_digest_class configurado como SHA-1 (el valor predeterminado antes de Rails 7.0), necesita configurar SHA-1 para el cifrado de Active Record también:

    config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1
    
  2. Si tiene config.active_support.key_generator_hash_digest_class configurado como SHA-256 (el nuevo valor predeterminado en 7.0), entonces necesita configurar SHA-256 para el cifrado de Active Record:

    config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA256
    

Consulte la guía Configuring Rails Applications para obtener más información sobre config.active_record.encryption.hash_digest_class.

Además, se introdujo una nueva configuración config.active_record.encryption.support_sha1_for_non_deterministic_encryption para resolver un error que causaba que algunos atributos se cifraran usando SHA-1 incluso cuando SHA-256 estaba configurado a través de la configuración mencionada anteriormente hash_digest_class.

Por defecto, config.active_record.encryption.support_sha1_for_non_deterministic_encryption está deshabilitado en Rails 7.1. Si tiene datos cifrados en una versión de Rails < 7.1 que cree que puede estar afectada por el error mencionado anteriormente, esta configuración debe habilitarse:

config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true

Si está trabajando con datos cifrados, revise cuidadosamente lo anterior.

3.13 Nuevas formas de manejar excepciones en Pruebas de Controladores, Pruebas de Integración y Pruebas de Sistema

La configuración config.action_dispatch.show_exceptions controla cómo Action Pack maneja las excepciones generadas mientras responde a solicitudes.

Antes de Rails 7.1, configurar config.action_dispatch.show_exceptions = true configuraba Action Pack para rescatar excepciones y renderizar páginas de error HTML apropiadas, como renderizar public/404.html con un código de estado 404 Not found en lugar de generar una excepción ActiveRecord::RecordNotFound. Configurar config.action_dispatch.show_exceptions = false configuraba Action Pack para no rescatar la excepción. Antes de Rails 7.1, las nuevas aplicaciones se generaban con una línea en config/environments/test.rb que configuraba config.action_dispatch.show_exceptions = false.

Rails 7.1 cambia los valores aceptables de true y false a :all, :rescuable y :none.

  • :all - renderizar páginas de error HTML para todas las excepciones (equivalente a true)
  • :rescuable - renderizar páginas de error HTML para excepciones declaradas por config.action_dispatch.rescue_responses
  • :none (equivalente a false) - no rescatar ninguna excepción

Las aplicaciones generadas por Rails 7.1 o posteriores configuran config.action_dispatch.show_exceptions = :rescuable en su config/environments/test.rb. Al actualizar, las aplicaciones existentes pueden cambiar config.action_dispatch.show_exceptions = :rescuable para utilizar el nuevo comportamiento, o reemplazar los valores antiguos con los nuevos correspondientes (true reemplaza :all, false reemplaza :none).

4 Actualización de Rails 6.1 a Rails 7.0

Para obtener más información sobre los cambios realizados en Rails 7.0, consulte las notas de lanzamiento.

4.1 Cambió el comportamiento de ActionView::Helpers::UrlHelper#button_to

A partir de Rails 7.0, button_to renderiza una etiqueta form con el verbo HTTP patch si se utiliza un objeto Active Record persistente para construir la URL del botón. Para mantener el comportamiento actual, considere pasar explícitamente la opción method::

-button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)], method: :post)

o usar un helper para construir la URL:

-button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("Do a POST", my_custom_post_action_on_workshop_workshop_path(Workshop.find(1)))

4.2 Spring

Si su aplicación usa Spring, necesita actualizarlo al menos a la versión 3.0.0. De lo contrario, recibirá

undefined method `mechanism=' for ActiveSupport::Dependencies:Module

Además, asegúrese de que config.cache_classes esté configurado en false en config/environments/test.rb.

4.3 Sprockets ahora es una dependencia opcional

El gem rails ya no depende de sprockets-rails. Si su aplicación aún necesita usar Sprockets, asegúrese de agregar sprockets-rails a su Gemfile.

gem "sprockets-rails"

4.4 Las aplicaciones deben ejecutarse en modo zeitwerk

Las aplicaciones que aún se ejecutan en modo classic deben cambiar a modo zeitwerk. Consulte la guía Classic to Zeitwerk HOWTO para obtener detalles.

4.5 El setter config.autoloader= ha sido eliminado

En Rails 7 no hay un punto de configuración para establecer el modo de carga automática, config.autoloader= ha sido eliminado. Si lo tenía configurado como :zeitwerk por cualquier razón, simplemente elimínelo.

4.6 La API privada de ActiveSupport::Dependencies ha sido eliminada

La API privada de ActiveSupport::Dependencies ha sido eliminada. Esto incluye métodos como hook!, unhook!, depend_on, require_or_load, mechanism y muchos otros.

Algunos de los aspectos destacados:

  • Si usaba ActiveSupport::Dependencies.constantize o ActiveSupport::Dependencies.safe_constantize, simplemente cámbielos por String#constantize o String#safe_constantize.
  ActiveSupport::Dependencies.constantize("User") # YA NO ES POSIBLE
  "User".constantize # 👍
  • Cualquier uso de ActiveSupport::Dependencies.mechanism, lector o escritor, debe ser reemplazado accediendo a config.cache_classes en consecuencia.

  • Si desea rastrear la actividad del cargador automático, ActiveSupport::Dependencies.verbose= ya no está disponible, simplemente arroje Rails.autoloaders.log! en config/application.rb.

Las clases o módulos internos auxiliares también se han ido, como ActiveSupport::Dependencies::Reference, ActiveSupport::Dependencies::Blamable y otros.

4.7 Carga automática durante la inicialización

Las aplicaciones que cargaron automáticamente constantes recargables durante la inicialización fuera de los bloques de to_prepare obtuvieron esas constantes descargadas y se emitió esta advertencia desde Rails 6.0:

DEPRECATION WARNING: Initialization autoloaded the constant ....

Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.

...

Si aún recibe esta advertencia en los registros, consulte la sección sobre carga automática cuando la aplicación se inicia en la guía de carga automática. De lo contrario, obtendría un NameError en Rails 7.

Las constantes gestionadas por el cargador automático once pueden ser cargadas automáticamente durante la inicialización y pueden ser usadas normalmente, no es necesario un bloque to_prepare. Sin embargo, el cargador automático once ahora se configura antes para soportar eso. Si la aplicación tiene inflexiones personalizadas y el cargador automático once debe ser consciente de ellas, necesita mover el código en config/initializers/inflections.rb al cuerpo de la definición de la clase de la aplicación en config/application.rb:

module MyApp
  class Application < Rails::Application
    # ...

    ActiveSupport::Inflector.inflections(:en) do |inflect|
      inflect.acronym "HTML"
    end
  end
end

4.8 Capacidad de configurar config.autoload_once_paths

config.autoload_once_paths se puede configurar en el cuerpo de la clase de la aplicación definida en config/application.rb o en la configuración para entornos en config/environments/*.

De manera similar, los motores pueden configurar esa colección en el cuerpo de la clase del motor o en la configuración para entornos.

Después de eso, la colección se congela y puede cargar automáticamente desde esas rutas. En particular, puede cargar automáticamente desde allí durante la inicialización. Son gestionadas por el cargador automático Rails.autoloaders.once, que no recarga, solo carga automáticamente/carga ansiosamente.

Si configuró esta configuración después de que se haya procesado la configuración de los entornos y está obteniendo FrozenError, simplemente mueva el código.

4.9 ActionDispatch::Request#content_type ahora devuelve el encabezado Content-Type tal como es.

Anteriormente, el valor devuelto de ActionDispatch::Request#content_type NO contenía la parte de charset. Este comportamiento cambió para devolver el encabezado Content-Type que contiene la parte de charset tal como es.

Si solo desea el tipo MIME, use ActionDispatch::Request#media_type en su lugar.

Antes:

request = ActionDispatch::Request.new("CONTENT_TYPE" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
request.content_type #=> "text/csv"

Después:

request = ActionDispatch::Request.new("Content-Type" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
request.content_type #=> "text/csv; header=present; charset=utf-16"
request.media_type   #=> "text/csv"

4.10 El cambio de clase digest del generador de claves requiere un rotador de cookies

La clase digest predeterminada para el generador de claves está cambiando de SHA1 a SHA256. Esto tiene consecuencias en cualquier mensaje cifrado generado por Rails, incluidas las cookies cifradas.

Para poder leer mensajes usando la clase digest antigua, es necesario registrar un rotador. No hacerlo puede resultar en que los usuarios tengan sus sesiones invalidadas durante la actualización.

El siguiente es un ejemplo de rotador para las cookies cifradas y firmadas.

# config/initializers/cookie_rotator.rb
Rails.application.config.after_initialize do
  Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies|
    authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt
    signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt

    secret_key_base = Rails.application.secret_key_base

    key_generator = ActiveSupport::KeyGenerator.new(
      secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1
    )
    key_len = ActiveSupport::MessageEncryptor.key_len

    old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len)
    old_signed_secret = key_generator.generate_key(signed_cookie_salt)

    cookies.rotate :encrypted, old_encrypted_secret
    cookies.rotate :signed, old_signed_secret
  end
end

4.11 Cambio de clase digest para ActiveSupport::Digest a SHA256

La clase digest predeterminada para ActiveSupport::Digest está cambiando de SHA1 a SHA256. Esto tiene consecuencias para cosas como los Etags que cambiarán y las claves de caché también. Cambiar estas claves puede tener un impacto en las tasas de aciertos de caché, así que tenga cuidado y esté atento a esto al actualizar al nuevo hash.

4.12 Nuevo formato de serialización de caché en ActiveSupport

Se introdujo un formato de serialización más rápido y compacto.

Para habilitarlo, debe establecer config.active_support.cache_format_version = 7.0:

# config/application.rb

config.load_defaults 6.1
config.active_support.cache_format_version = 7.0

O simplemente:

# config/application.rb

config.load_defaults 7.0

Sin embargo, las aplicaciones de Rails 6.1 no pueden leer este nuevo formato de serialización, por lo que para garantizar una actualización sin problemas, primero debe implementar su actualización de Rails 7.0 con config.active_support.cache_format_version = 6.1, y luego, solo una vez que todos los procesos de Rails se hayan actualizado, puede establecer config.active_support.cache_format_version = 7.0.

Rails 7.0 puede leer ambos formatos, por lo que la caché no se invalidará durante la actualización.

4.13 Generación de imágenes de vista previa de video en Active Storage

La generación de imágenes de vista previa de video ahora utiliza la detección de cambios de escena de FFmpeg para generar imágenes de vista previa más significativas. Anteriormente, se utilizaba el primer fotograma del video y eso causaba problemas si el video se desvanecía de negro. Este cambio requiere FFmpeg v3.4+.

4.14 Procesador de variantes predeterminado de Active Storage cambiado a :vips

Para nuevas aplicaciones, la transformación de imágenes usará libvips en lugar de ImageMagick. Esto reducirá el tiempo necesario para generar variantes, así como el uso de CPU y memoria, mejorando los tiempos de respuesta en aplicaciones que dependen de Active Storage para servir sus imágenes.

La opción :mini_magick no está siendo desaprobada, por lo que está bien seguir usándola.

Para migrar una aplicación existente a libvips, configure:

Rails.application.config.active_storage.variant_processor = :vips

Luego deberá cambiar el código de transformación de imágenes existente a los macros de image_processing y reemplazar las opciones de ImageMagick con las opciones de libvips.

4.14.1 Reemplace resize con resize_to_limit

- variant(resize: "100x")
+ variant(resize_to_limit: [100, nil])

Si no hace esto, cuando cambie a vips verá este error: no implicit conversion to float from string.

4.14.2 Use una matriz al recortar

- variant(crop: "1920x1080+0+0")
+ variant(crop: [0, 0, 1920, 1080])

Si no hace esto al migrar a vips, verá el siguiente error: unable to call crop: you supplied 2 arguments, but operation needs 5.

4.14.3 Ajuste los valores de recorte:

Vips es más estricto que ImageMagick cuando se trata de recortar:

  1. No recortará si x y/o y son valores negativos. por ejemplo: [-10, -10, 100, 100]
  2. No recortará si la posición (x o y) más la dimensión de recorte (width, height) es mayor que la imagen. por ejemplo: una imagen de 125x125 y un recorte de [50, 50, 100, 100]

Si no hace esto al migrar a vips, verá el siguiente error: extract_area: bad extract area

4.14.4 Ajuste el color de fondo utilizado para resize_and_pad

Vips usa negro como el color de fondo predeterminado para resize_and_pad, en lugar de blanco como ImageMagick. Solucione eso usando la opción background:

- variant(resize_and_pad: [300, 300])
+ variant(resize_and_pad: [300, 300, background: [255]])

4.14.5 Elimine cualquier rotación basada en EXIF

Vips rotará automáticamente las imágenes usando el valor EXIF al procesar variantes. Si estaba almacenando valores de rotación de fotos cargadas por el usuario para aplicar la rotación con ImageMagick, debe dejar de hacerlo:

- variant(format: :jpg, rotate: rotation_value)
+ variant(format: :jpg)

4.14.6 Reemplace monochrome con colourspace

Vips usa una opción diferente para hacer imágenes monocromáticas:

- variant(monochrome: true)
+ variant(colourspace: "b-w")

4.14.7 Cambie a opciones de libvips para comprimir imágenes

JPEG

- variant(strip: true, quality: 80, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB")
+ variant(saver: { strip: true, quality: 80, interlace: true })

PNG

- variant(strip: true, quality: 75)
+ variant(saver: { strip: true, compression: 9 })

WEBP

- variant(strip: true, quality: 75, define: { webp: { lossless: false, alpha_quality: 85, thread_level: 1 } })
+ variant(saver: { strip: true, quality: 75, lossless: false, alpha_q: 85, reduction_effort: 6, smart_subsample: true })

GIF

- variant(layers: "Optimize")
+ variant(saver: { optimize_gif_frames: true, optimize_gif_transparency: true })

4.14.8 Despliegue a producción

Active Storage codifica en la URL de la imagen la lista de transformaciones que deben realizarse. Si su aplicación está almacenando en caché estas URL, sus imágenes se romperán después de implementar el nuevo código en producción. Debido a esto, debe invalidar manualmente sus claves de caché afectadas.

Por ejemplo, si tiene algo como esto en una vista:

<% @products.each do |product| %>
  <% cache product do %>
    <%= image_tag product.cover_photo.variant(resize: "200x") %>
  <% end %>
<% end %>

Puede invalidar la caché tocando el producto o cambiando la clave de caché:

<% @products.each do |product| %>
  <% cache ["v2", product] do %>
    <%= image_tag product.cover_photo.variant(resize_to_limit: [200, nil]) %>
  <% end %>
<% end %>

4.15 La versión de Rails ahora se incluye en el volcado de esquema de Active Record

Rails 7.0 cambió algunos valores predeterminados para algunos tipos de columnas. Para evitar que las aplicaciones que se actualizan de 6.1 a 7.0 carguen el esquema actual usando los nuevos valores predeterminados de 7.0, Rails ahora incluye la versión del framework en el volcado de esquema.

Antes de cargar el esquema por primera vez en Rails 7.0, asegúrese de ejecutar rails app:update para garantizar que la versión del esquema se incluya en el volcado de esquema.

El archivo de esquema se verá así:

# Este archivo se genera automáticamente a partir del estado actual de la base de datos. En lugar
# de editar este archivo, utilice la función de migraciones de Active Record para
# modificar su base de datos de manera incremental y luego regenere esta definición de esquema.
#
# Este archivo es la fuente que Rails utiliza para definir su esquema al ejecutar `bin/rails
# db:schema:load`. Al crear una nueva base de datos, `bin/rails db:schema:load` tiende a
# ser más rápido y es potencialmente menos propenso a errores que ejecutar todas sus
# migraciones desde cero. Las migraciones antiguas pueden fallar al aplicarse correctamente si esas
# migraciones utilizan dependencias externas o código de aplicación.
#
# Se recomienda encarecidamente que registre este archivo en su sistema de control de versiones.

ActiveRecord::Schema[6.1].define(version: 2022_01_28_123512) do
  # ...
end

NOTA: La primera vez que realice un volcado del esquema con Rails 7.0, verá muchos cambios en ese archivo, incluida información de algunas columnas. Asegúrese de revisar el nuevo contenido del archivo de esquema y comprometerlo en su repositorio.

5 Actualización de Rails 6.0 a Rails 6.1

Para obtener más información sobre los cambios realizados en Rails 6.1, consulte las notas de lanzamiento.

5.1 El valor de retorno de Rails.application.config_for ya no admite el acceso con claves de cadena.

Dado un archivo de configuración como este:

# config/example.yml
development:
  options:
    key: value
Rails.application.config_for(:example).options

Esto solía devolver un hash en el que podía acceder a los valores con claves de cadena. Eso estaba desaprobado en 6.0 y ahora ya no funciona.

Puede llamar a with_indifferent_access en el valor de retorno de config_for si aún desea acceder a los valores con claves de cadena, por ejemplo:

Rails.application.config_for(:example).with_indifferent_access.dig('options', 'key')

5.2 Tipo de contenido de la respuesta al usar respond_to#any

El encabezado Content-Type devuelto en la respuesta puede diferir de lo que Rails 6.0 devolvía, más específicamente si su aplicación usa respond_to { |format| format.any }. El Content-Type ahora se basará en el bloque dado en lugar del formato de la solicitud.

Ejemplo:

def my_action
  respond_to do |format|
    format.any { render(json: { foo: 'bar' }) }
  end
end
get('my_action.csv')

El comportamiento anterior devolvía un Content-Type de respuesta text/csv, lo cual es inexacto ya que se está renderizando una respuesta JSON. El comportamiento actual devuelve correctamente un Content-Type de respuesta application/json.

Si su aplicación depende del comportamiento incorrecto anterior, se le recomienda especificar qué formatos acepta su acción, es decir:

format.any(:xml, :json) { render request.format.to_sym => @people }

5.3 ActiveSupport::Callbacks#halted_callback_hook ahora recibe un segundo argumento

Active Support permite anular el halted_callback_hook cuando una devolución de llamada detiene la cadena. Este método ahora recibe un segundo argumento que es el nombre de la devolución de llamada que se detiene. Si tiene clases que anulan este método, asegúrese de que acepte dos argumentos. Tenga en cuenta que este es un cambio que rompe la compatibilidad sin un ciclo de desaprobación previo (por razones de rendimiento).

Ejemplo:

class Book < ApplicationRecord
  before_save { throw(:abort) }
  before_create { throw(:abort) }

  def halted_callback_hook(filter, callback_name) # => Este método ahora acepta 2 argumentos en lugar de 1
    Rails.logger.info("Book couldn't be #{callback_name}d")
  end
end

5.4 El método de clase helper en controladores usa String#constantize

Conceptualmente, antes de Rails 6.1

helper "foo/bar"

resultaba en

require_dependency "foo/bar_helper"
module_name = "foo/bar_helper".camelize
module_name.constantize

Ahora hace esto en su lugar:

prefix = "foo/bar".camelize
"#{prefix}Helper".constantize

Este cambio es compatible con versiones anteriores para la mayoría de las aplicaciones, en cuyo caso no necesita hacer nada.

Técnicamente, sin embargo, los controladores podrían configurar helpers_path para apuntar a un directorio en $LOAD_PATH que no estaba en las rutas de carga automática. Ese caso de uso ya no es compatible de forma predeterminada. Si el módulo de ayuda no se puede cargar automáticamente, la aplicación es responsable de cargarlo antes de llamar a helper.

5.5 La redirección a HTTPS desde HTTP ahora usará el código de estado HTTP 308

El código de estado HTTP predeterminado utilizado en ActionDispatch::SSL al redirigir solicitudes no GET/HEAD de HTTP a HTTPS ha cambiado a 308 como se define en https://tools.ietf.org/html/rfc7538.

5.6 Active Storage ahora requiere Image Processing

Al procesar variantes en Active Storage, ahora es necesario tener el gem image_processing incluido en lugar de usar directamente mini_magick. Image Processing está configurado de manera predeterminada para usar mini_magick detrás de escena, por lo que la forma más fácil de actualizar es reemplazar el gem mini_magick por el gem image_processing y asegurarse de eliminar el uso explícito de combine_options ya que ya no es necesario.

Para mayor legibilidad, puede desear cambiar las llamadas resize sin procesar a macros de image_processing. Por ejemplo, en lugar de:

video.preview(resize: "100x100")
video.preview(resize: "100x100>")
video.preview(resize: "100x100^")

puede hacer respectivamente:

video.preview(resize_to_fit: [100, 100])
video.preview(resize_to_limit: [100, 100])
video.preview(resize_to_fill: [100, 100])

5.7 Nueva clase ActiveModel::Error

Los errores ahora son instancias de una nueva clase ActiveModel::Error, con cambios en la API. Algunos de estos cambios pueden generar errores dependiendo de cómo manipule los errores, mientras que otros imprimirán advertencias de desaprobación para ser corregidos en Rails 7.0.

Puede encontrar más información sobre este cambio y detalles sobre los cambios en la API en este PR.

6 Actualización de Rails 5.2 a Rails 6.0

Para obtener más información sobre los cambios realizados en Rails 6.0, consulte las notas de lanzamiento.

6.1 Uso de Webpacker

Webpacker es el compilador de JavaScript predeterminado para Rails 6. Pero si está actualizando la aplicación, no se activa de manera predeterminada. Si desea usar Webpacker, inclúyalo en su Gemfile e instálelo:

gem "webpacker"
$ bin/rails webpacker:install

6.2 Forzar SSL

El método force_ssl en los controladores ha sido desaprobado y se eliminará en Rails 6.1. Se le recomienda habilitar config.force_ssl para forzar conexiones HTTPS en toda su aplicación. Si necesita eximir ciertos puntos finales de la redirección, puede usar config.ssl_options para configurar ese comportamiento.

6.3 El propósito y la expiración de los metadatos ahora están incrustados dentro de las cookies firmadas y cifradas para aumentar la seguridad

Para mejorar la seguridad, Rails incrusta el propósito y la expiración de los metadatos dentro del valor de las cookies cifradas o firmadas.

Rails puede frustrar los ataques que intentan copiar el valor firmado/cifrado de una cookie y usarlo como el valor de otra cookie.

Esta nueva incrustación de metadatos hace que esas cookies sean incompatibles con versiones de Rails anteriores a 6.0.

Si necesita que sus cookies sean leídas por Rails 5.2 y versiones anteriores, o aún está validando su implementación de 6.0 y desea poder revertir, establezca Rails.application.config.action_dispatch.use_cookies_with_metadata en false.

6.4 Todos los paquetes npm se han movido al alcance @rails

Si anteriormente estaba cargando alguno de los paquetes actioncable, activestorage o rails-ujs a través de npm/yarn, debe actualizar los nombres de estas dependencias antes de poder actualizarlas a 6.0.0:

actioncable   → @rails/actioncable
activestorage → @rails/activestorage
rails-ujs     → @rails/ujs

6.5 Cambios en la API de JavaScript de Action Cable

El paquete de JavaScript de Action Cable se ha convertido de CoffeeScript a ES2015, y ahora publicamos el código fuente en la distribución npm.

Esta versión incluye algunos cambios importantes en las partes opcionales de la API de JavaScript de Action Cable:

  • La configuración del adaptador WebSocket y del adaptador logger se ha movido de propiedades de ActionCable a propiedades de ActionCable.adapters. Si está configurando estos adaptadores, deberá realizar estos cambios:

    -    ActionCable.WebSocket = MyWebSocket
    +    ActionCable.adapters.WebSocket = MyWebSocket
    
    -    ActionCable.logger = myLogger
    +    ActionCable.adapters.logger = myLogger
    
  • Los métodos ActionCable.startDebugging() y ActionCable.stopDebugging() se han eliminado y se han reemplazado con la propiedad ActionCable.logger.enabled. Si está utilizando estos métodos, deberá realizar estos cambios:

    -    ActionCable.startDebugging()
    +    ActionCable.logger.enabled = true
    
    -    ActionCable.stopDebugging()
    +    ActionCable.logger.enabled = false
    

6.6 ActionDispatch::Response#content_type ahora devuelve el encabezado Content-Type sin modificación

Anteriormente, el valor devuelto de ActionDispatch::Response#content_type NO contenía la parte de charset. Este comportamiento ha cambiado para incluir la parte de charset previamente omitida también.

Si solo desea el tipo MIME, use ActionDispatch::Response#media_type en su lugar.

Antes:

resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present"

Después:

resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present; charset=utf-16"
resp.media_type   #=> "text/csv"

6.7 Nueva configuración config.hosts

Rails ahora tiene una nueva configuración config.hosts por razones de seguridad. Esta configuración predetermina localhost en desarrollo. Si usa otros dominios en desarrollo, necesita permitirlos así:

# config/environments/development.rb

config.hosts << 'dev.myapp.com'
config.hosts << /[a-z0-9-]+\.myapp\.com/ # Opcionalmente, también se permite una expresión regular

Para otros entornos, config.hosts está vacío por defecto, lo que significa que Rails no validará el host en absoluto. Puede agregarlos opcionalmente si desea validarlo en producción.

6.8 Carga automática

La configuración predeterminada para Rails 6

# config/application.rb

config.load_defaults 6.0

habilita el modo de carga automática zeitwerk en CRuby. En ese modo, la carga automática, la recarga y la carga ansiosa son gestionadas por Zeitwerk.

Si está utilizando los valores predeterminados de una versión anterior de Rails, puede habilitar zeitwerk así:

# config/application.rb

config.autoloader = :zeitwerk

6.8.1 API Pública

En general, las aplicaciones no necesitan usar la API de Zeitwerk directamente. Rails configura las cosas de acuerdo con el contrato existente: config.autoload_paths, config.cache_classes, etc.

Aunque las aplicaciones deben ceñirse a esa interfaz, el objeto del cargador automático Zeitwerk real se puede acceder como

Rails.autoloaders.main

Eso puede ser útil si necesita precargar clases de Herencia de Tabla Única (STI) o configurar un inflector personalizado, por ejemplo.

6.8.2 Estructura del Proyecto

Si la aplicación que se está actualizando carga automáticamente correctamente, la estructura del proyecto debería ser ya mayormente compatible.

Sin embargo, el modo classic infiere nombres de archivos a partir de nombres de constantes faltantes (underscore), mientras que el modo zeitwerk infiere nombres de constantes a partir de nombres de archivos (camelize). Estos ayudantes no siempre son inversos entre sí, en particular si están involucrados acrónimos. Por ejemplo, "FOO".underscore es "foo", pero "foo".camelize es "Foo", no "FOO".

La compatibilidad se puede verificar con la tarea zeitwerk:check:

$ bin/rails zeitwerk:check
Hold on, I am eager loading the application.
All is good!

6.8.3 require_dependency

Todos los casos de uso conocidos de require_dependency han sido eliminados, debe buscar en el proyecto y eliminarlos.

Si su aplicación utiliza Herencia de Tabla Única, consulte la sección de Herencia de Tabla Única de la guía de Carga Automática y Recarga de Constantes (Modo Zeitwerk).

6.8.4 Nombres calificados en definiciones de clases y módulos

Ahora puede usar de manera robusta rutas constantes en definiciones de clases y módulos:

# La carga automática en el cuerpo de esta clase ahora coincide con la semántica de Ruby.
class Admin::UsersController < ApplicationController
  # ...
end

Un inconveniente a tener en cuenta es que, dependiendo del orden de ejecución, el cargador automático clásico a veces podría ser capaz de cargar automáticamente Foo::Wadus en

class Foo::Bar
  Wadus
end

Eso no coincide con la semántica de Ruby porque Foo no está en el anidamiento, y no funcionará en absoluto en el modo zeitwerk. Si encuentra tal caso, puede usar el nombre calificado Foo::Wadus:

class Foo::Bar
  Foo::Wadus
end

o agregar Foo al anidamiento:

module Foo
  class Bar
    Wadus
  end
end

6.8.5 Concerns

Puede cargar automáticamente y cargar ansiosamente desde una estructura estándar como

app/models
app/models/concerns

En ese caso, se asume que app/models/concerns es un directorio raíz (porque pertenece a las rutas de carga automática) y se ignora como espacio de nombres. Entonces, app/models/concerns/foo.rb debería definir Foo, no Concerns::Foo.

El espacio de nombres Concerns:: funcionó con el cargador automático clásico como un efecto secundario de la implementación, pero realmente no era un comportamiento intencionado. Una aplicación que usa Concerns:: necesita renombrar esas clases y módulos para poder ejecutarse en modo zeitwerk.

6.8.6 Tener app en las rutas de carga automática

Algunos proyectos quieren algo como app/api/base.rb para definir API::Base, y agregan app a las rutas de carga automática para lograr eso en modo classic. Dado que Rails agrega automáticamente todos los subdirectorios de app a las rutas de carga automática, tenemos otra situación en la que hay directorios raíz anidados, por lo que esa configuración ya no funciona. Principio similar que explicamos anteriormente con concerns.

Si desea mantener esa estructura, deberá eliminar el subdirectorio de las rutas de carga automática en un inicializador:

ActiveSupport::Dependencies.autoload_paths.delete("#{Rails.root}/app/api")

6.8.7 Constantes Cargadas Automáticamente y Espacios de Nombres Explícitos

Si un espacio de nombres se define en un archivo, como Hotel aquí:

app/models/hotel.rb         # Define Hotel.
app/models/hotel/pricing.rb # Define Hotel::Pricing.

la constante Hotel debe establecerse usando las palabras clave class o module. Por ejemplo:

class Hotel
end

es bueno.

Alternativas como

Hotel = Class.new

o

Hotel = Struct.new

no funcionarán, los objetos secundarios como Hotel::Pricing no se encontrarán.

Esta restricción solo se aplica a espacios de nombres explícitos. Las clases y módulos que no definen un espacio de nombres se pueden definir usando esos idioms.

6.8.8 Un archivo, una constante (en el mismo nivel superior)

En el modo classic técnicamente podría definir varias constantes en el mismo nivel superior y hacer que todas se recargaran. Por ejemplo, dado

# app/models/foo.rb

class Foo
end

class Bar
end

mientras que Bar no podría ser cargado automáticamente, cargar automáticamente Foo marcaría Bar como cargado automáticamente también. Este no es el caso en modo zeitwerk, necesita mover Bar a su propio archivo bar.rb. Un archivo, una constante.

Esto solo se aplica a las constantes en el mismo nivel superior como en el ejemplo anterior. Las clases y módulos internos están bien. Por ejemplo, considere

# app/models/foo.rb

class Foo
  class InnerClass
  end
end

Si la aplicación recarga Foo, también recargará Foo::InnerClass.

6.8.9 Spring y el Entorno test

Spring recarga el código de la aplicación si algo cambia. En el entorno test, necesita habilitar la recarga para que eso funcione:

# config/environments/test.rb

config.cache_classes = false

De lo contrario, obtendrá este error:

reloading is disabled because config.cache_classes is true

6.8.10 Bootsnap

Bootsnap debe ser al menos la versión 1.4.2.

Además de eso, Bootsnap necesita deshabilitar la caché iseq debido a un error en el intérprete si se ejecuta Ruby 2.5. Asegúrese de depender al menos de Bootsnap 1.4.4 en ese caso.

6.8.11 config.add_autoload_paths_to_load_path

El nuevo punto de configuración config.add_autoload_paths_to_load_path es true de manera predeterminada para la compatibilidad con versiones anteriores, pero le permite optar por no agregar las rutas de carga automática a $LOAD_PATH.

Esto tiene sentido en la mayoría de las aplicaciones, ya que nunca debería requerir un archivo en app/models, por ejemplo, y Zeitwerk solo usa nombres de archivos absolutos internamente.

Al optar por no hacerlo, optimiza las búsquedas de $LOAD_PATH (menos directorios para verificar) y ahorra trabajo y consumo de memoria de Bootsnap, ya que no necesita construir un índice para estos directorios.

6.8.12 Seguridad de Hilos

En modo clásico, la carga automática de constantes no es segura para hilos, aunque Rails tiene bloqueos en su lugar, por ejemplo, para hacer que las solicitudes web sean seguras para hilos cuando la carga automática está habilitada, como es común en el entorno de desarrollo.

La carga automática de constantes es segura para hilos en modo zeitwerk. Por ejemplo, ahora puede cargar automáticamente en scripts multihilo ejecutados por el comando runner.

6.8.13 Globos en config.autoload_paths

Tenga cuidado con configuraciones como

config.autoload_paths += Dir["#{config.root}/lib/**/"]

Cada elemento de config.autoload_paths debe representar el espacio de nombres de nivel superior (Object) y no pueden estar anidados en consecuencia (con la excepción de los directorios concerns explicados anteriormente).

Para solucionar esto, simplemente elimine los comodines:

config.autoload_paths << "#{config.root}/lib"

6.8.14 La carga ansiosa y la carga automática son consistentes

En modo classic, si app/models/foo.rb define Bar, no podrá cargar automáticamente ese archivo, pero la carga ansiosa funcionará porque carga archivos de manera recursiva a ciegas. Esto puede ser una fuente de errores si prueba cosas primero cargando ansiosamente, la ejecución puede fallar más tarde cargando automáticamente.

En modo zeitwerk, ambos modos de carga son consistentes, fallan y erran en los mismos archivos.

6.8.15 Cómo Usar el Cargador Automático Clásico en Rails 6

Las aplicaciones pueden cargar los valores predeterminados de Rails 6 y aún usar el cargador automático clásico configurando config.autoloader de esta manera:

# config/application.rb

config.load_defaults 6.0
config.autoloader = :classic

Al usar el Cargador Automático Clásico en la aplicación Rails 6, se recomienda establecer el nivel de concurrencia en 1 en el entorno de desarrollo, para los servidores web y procesadores en segundo plano, debido a las preocupaciones de seguridad de hilos.

6.9 Cambio en el Comportamiento de Asignación de Active Storage

Con los valores de configuración predeterminados para Rails 5.2, asignar a una colección de archivos adjuntos declarados con has_many_attached agrega nuevos archivos:

class User < ApplicationRecord
  has_many_attached :highlights
end

user.highlights.attach(filename: "funky.jpg")
user.highlights.count # => 1

blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.update!(highlights: [ blob ])

user.highlights.count # => 2
user.highlights.first.filename # => "funky.jpg"
user.highlights.second.filename # => "town.jpg"

Con los valores de configuración predeterminados para Rails 6.0, asignar a una colección de archivos adjuntos reemplaza los archivos existentes en lugar de agregarlos. Esto coincide con el comportamiento de Active Record al asignar a una asociación de colección:

user.highlights.attach(filename: "funky.jpg")
user.highlights.count # => 1

blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.update!(highlights: [ blob ])

user.highlights.count # => 1
user.highlights.first.filename # => "town.jpg"

#attach se puede usar para agregar nuevos archivos adjuntos sin eliminar los existentes:

blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.highlights.attach(blob)

user.highlights.count # => 2
user.highlights.first.filename # => "funky.jpg"
user.highlights.second.filename # => "town.jpg"

Las aplicaciones existentes pueden optar por este nuevo comportamiento configurando config.active_storage.replace_on_assign_to_many en true. El comportamiento anterior será desaprobado en Rails 7.0 y eliminado en Rails 7.1.

6.10 Aplicaciones de Manejo de Excepciones Personalizadas

Las cabeceras de solicitud Accept o Content-Type inválidas ahora generarán una excepción. La aplicación de excepciones predeterminada config.exceptions_app maneja específicamente ese error y lo compensa. Las aplicaciones de excepciones personalizadas deberán manejar ese error también, o tales solicitudes harán que Rails use la aplicación de excepciones de respaldo, que devuelve un 500 Internal Server Error.

7 Actualización de Rails 5.1 a Rails 5.2

Para obtener más información sobre los cambios realizados en Rails 5.2, consulte las notas de lanzamiento.

7.1 Bootsnap

Rails 5.2 agrega el gem bootsnap en el Gemfile de la nueva aplicación generada. El comando app:update lo configura en boot.rb. Si desea usarlo, agréguelo en el Gemfile:

# Reduce los tiempos de arranque mediante el almacenamiento en caché; requerido en config/boot.rb
gem "bootsnap", require: false

De lo contrario, cambie el boot.rb para no usar bootsnap.

7.2 La expiración en cookies firmadas o cifradas ahora está incrustada en los valores de las cookies

Para mejorar la seguridad, Rails ahora incrusta la información de expiración también en el valor de las cookies cifradas o firmadas.

Esta nueva información incrustada hace que esas cookies sean incompatibles con versiones de Rails anteriores a 5.2.

Si necesita que sus cookies sean leídas por 5.1 y versiones anteriores, o aún está validando su implementación de 5.2 y desea permitir que pueda revertir, establezca Rails.application.config.action_dispatch.use_authenticated_cookie_encryption en false.

8 Actualización de Rails 5.0 a Rails 5.1

Para obtener más información sobre los cambios realizados en Rails 5.1, consulte las notas de lanzamiento.

8.1 HashWithIndifferentAccess de nivel superior está en desuso

Si su aplicación utiliza la clase HashWithIndifferentAccess de nivel superior, debe mover su código lentamente para usar ActiveSupport::HashWithIndifferentAccess.

Solo está en desuso suavemente, lo que significa que su código no se romperá en este momento y no se mostrará ninguna advertencia de desaprobación, pero esta constante se eliminará en el futuro.

Además, si tiene documentos YAML bastante antiguos que contienen volcados de tales objetos, es posible que necesite cargarlos y volcarlos nuevamente para asegurarse de que hagan referencia a la constante correcta y que cargarlos no se rompa en el futuro.

8.2 application.secrets ahora se carga con todas las claves como símbolos

Si su aplicación almacena configuración anidada en config/secrets.yml, todas las claves ahora se cargan como símbolos, por lo que el acceso usando cadenas debe cambiarse.

De:

Rails.application.secrets[:smtp_settings]["address"]

A:

Rails.application.secrets[:smtp_settings][:address]

8.3 Eliminado soporte desaprobado para :text y :nothing en render

Si sus controladores están usando render :text, ya no funcionarán. El nuevo método de renderizar texto con tipo MIME de text/plain es usar render :plain.

Del mismo modo, render :nothing también se ha eliminado y debe usar el método head para enviar respuestas que solo contengan encabezados. Por ejemplo, head :ok envía una respuesta 200 sin cuerpo para renderizar.

8.4 Eliminado soporte desaprobado de redirect_to :back

En Rails 5.0, redirect_to :back fue desaprobado. En Rails 5.1, se eliminó por completo.

Como alternativa, use redirect_back. Es importante tener en cuenta que redirect_back también toma una opción fallback_location que se utilizará en caso de que falte el HTTP_REFERER.

redirect_back(fallback_location: root_path)

9 Actualización de Rails 4.2 a Rails 5.0

Para obtener más información sobre los cambios realizados en Rails 5.0, consulte las notas de lanzamiento.

9.1 Ruby 2.2.2+ requerido

A partir de Ruby on Rails 5.0 en adelante, Ruby 2.2.2+ es la única versión de Ruby compatible. Asegúrese de estar en la versión Ruby 2.2.2 o superior antes de continuar.

9.2 Los modelos de Active Record ahora heredan de ApplicationRecord por defecto

En Rails 4.2, un modelo de Active Record hereda de ActiveRecord::Base. En Rails 5.0, todos los modelos heredan de ApplicationRecord.

ApplicationRecord es una nueva superclase para todos los modelos de la aplicación, análoga a los controladores de la aplicación que subclasan ApplicationController en lugar de ActionController::Base. Esto le da a las aplicaciones un único lugar para configurar el comportamiento del modelo en toda la aplicación.

Al actualizar de Rails 4.2 a Rails 5.0, necesita crear un archivo application_record.rb en app/models/ y agregar el siguiente contenido:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

Luego asegúrese de que todos sus modelos hereden de él.

9.3 Detener cadenas de devoluciones de llamada a través de throw(:abort)

En Rails 4.2, cuando una devolución de llamada 'before' devuelve false en Active Record y Active Model, entonces se detiene toda la cadena de devoluciones de llamada. En otras palabras, las devoluciones de llamada 'before' sucesivas no se ejecutan, ni tampoco la acción envuelta en devoluciones de llamada.

En Rails 5.0, devolver false en una devolución de llamada de Active Record o Active Model no tendrá este efecto secundario de detener la cadena de devoluciones de llamada. En su lugar, las cadenas de devoluciones de llamada deben detenerse explícitamente llamando a throw(:abort).

Cuando actualice de Rails 4.2 a Rails 5.0, devolver false en ese tipo de devoluciones de llamada aún detendrá la cadena de devoluciones de llamada, pero recibirá una advertencia de desaprobación sobre este cambio próximo.

Cuando esté listo, puede optar por el nuevo comportamiento y eliminar la advertencia de desaprobación agregando la siguiente configuración a su config/application.rb:

ActiveSupport.halt_callback_chains_on_return_false = false

Tenga en cuenta que esta opción no afectará a las devoluciones de llamada de Active Support, ya que nunca detuvieron la cadena cuando se devolvía cualquier valor.

Consulte #17227 para obtener más detalles.

9.4 ActiveJob ahora hereda de ApplicationJob por defecto

En Rails 4.2, un Active Job hereda de ActiveJob::Base. En Rails 5.0, este comportamiento ha cambiado para heredar ahora de ApplicationJob.

Al actualizar de Rails 4.2 a Rails 5.0, necesita crear un archivo application_job.rb en app/jobs/ y agregar el siguiente contenido:

class ApplicationJob < ActiveJob::Base
end

Luego asegúrese de que todas sus clases de trabajo hereden de él.

Consulte #19034 para obtener más detalles.

9.5 Pruebas de Controladores de Rails

9.5.1 Extracción de algunos métodos auxiliares a rails-controller-testing

assigns y assert_template se han extraído al gem rails-controller-testing. Para continuar usando estos métodos en sus pruebas de controlador, agregue gem "rails-controller-testing" a su Gemfile.

Si está usando RSpec para las pruebas, consulte la configuración adicional requerida en la documentación del gem.

9.5.2 Nuevo comportamiento al subir archivos

Si está utilizando ActionDispatch::Http::UploadedFile en sus pruebas para subir archivos, necesitará cambiar para usar la clase similar Rack::Test::UploadedFile en su lugar.

Consulte #26404 para obtener más detalles.

9.6 La carga automática está deshabilitada después de iniciar en el entorno de producción

La carga automática ahora está deshabilitada después de iniciar en el entorno de producción de manera predeterminada.

La carga ansiosa de la aplicación es parte del proceso de inicio, por lo que las constantes de nivel superior están bien y aún se cargan automáticamente, no es necesario requerir sus archivos.

Las constantes en lugares más profundos que solo se ejecutan en tiempo de ejecución, como los cuerpos de métodos regulares, también están bien porque el archivo que los define se habrá cargado ansiosamente durante el inicio.

Para la gran mayoría de las aplicaciones, este cambio no necesita ninguna acción. Pero en el caso muy raro de que su aplicación necesite carga automática mientras se ejecuta en producción, configure Rails.application.config.enable_dependency_loading en true.

9.7 Serialización XML

ActiveModel::Serializers::Xml se ha extraído de Rails al gem activemodel-serializers-xml. Para continuar usando la serialización XML en su aplicación, agregue gem "activemodel-serializers-xml" a su Gemfile.

9.8 Eliminado soporte para adaptador de base de datos mysql heredado

Rails 5 elimina el soporte para el adaptador de base de datos mysql heredado. La mayoría de los usuarios deberían poder usar mysql2 en su lugar. Se convertirá en un gem separado cuando encontremos a alguien que lo mantenga.

9.9 Eliminado soporte para Debugger

debugger no es compatible con Ruby 2.2, que es requerido por Rails 5. Use byebug en su lugar.

9.10 Use bin/rails para ejecutar tareas y pruebas

Rails 5 agrega la capacidad de ejecutar tareas y pruebas a través de bin/rails en lugar de rake. Generalmente, estos cambios están en paralelo con rake, pero algunos se portaron por completo.

Para usar el nuevo ejecutor de pruebas, simplemente escriba bin/rails test.

rake dev:cache ahora es bin/rails dev:cache.

Ejecute bin/rails dentro del directorio raíz de su aplicación para ver la lista de comandos disponibles.

9.11 ActionController::Parameters ya no hereda de HashWithIndifferentAccess

Llamar a params en su aplicación ahora devolverá un objeto en lugar de un hash. Si sus parámetros ya están permitidos, entonces no necesitará hacer ningún cambio. Si está utilizando map y otros métodos que dependen de poder leer el hash independientemente de permitted?, necesitará actualizar su aplicación para primero permitir y luego convertir a un hash.

params.permit([:proceed_to, :return_to]).to_h

9.12 protect_from_forgery ahora predetermina prepend: false

protect_from_forgery predetermina prepend: false, lo que significa que se insertará en la cadena de devoluciones de llamada en el punto en que lo llame en su aplicación. Si desea que protect_from_forgery siempre se ejecute primero, debe cambiar su aplicación para usar protect_from_forgery prepend: true.

9.13 El manejador de plantillas predeterminado ahora es RAW

Los archivos sin un manejador de plantillas en su extensión se renderizarán usando el manejador raw. Anteriormente, Rails renderizaba archivos usando el manejador de plantillas ERB.

Si no desea que su archivo sea manejado a través del manejador raw, debe agregar una extensión a su archivo que pueda ser analizada por el manejador de plantillas apropiado.

9.14 Agregado coincidencia de comodines para dependencias de plantillas

Ahora puede usar coincidencia de comodines para sus dependencias de plantillas. Por ejemplo, si estaba definiendo sus plantillas de esta manera:

<% # Template Dependency: recordings/threads/events/subscribers_changed %>
<% # Template Dependency: recordings/threads/events/completed %>
<% # Template Dependency: recordings/threads/events/uncompleted %>

Ahora puede simplemente llamar a la dependencia una vez con un comodín.

<% # Template Dependency: recordings/threads/events/* %>

9.15 ActionView::Helpers::RecordTagHelper movido a un gem externo (record_tag_helper)

content_tag_for y div_for se han eliminado en favor de simplemente usar content_tag. Para continuar usando los métodos anteriores, agregue el gem record_tag_helper a su Gemfile:

gem "record_tag_helper", "~> 1.0"

Consulte #18411 para obtener más detalles.

9.16 Eliminado soporte para el gem protected_attributes

El gem protected_attributes ya no es compatible en Rails 5.

9.17 Eliminado soporte para el gem activerecord-deprecated_finders

El gem activerecord-deprecated_finders ya no es compatible en Rails 5.

9.18 El orden de prueba predeterminado de ActiveSupport::TestCase ahora es aleatorio

Cuando se ejecutan pruebas en su aplicación, el orden predeterminado ahora es :random en lugar de :sorted. Use la siguiente opción de configuración para establecerlo de nuevo en :sorted.

# config/environments/test.rb
Rails.application.configure do
  config.active_support.test_order = :sorted
end

9.19 ActionController::Live se convirtió en un Concern

Si incluye ActionController::Live en otro módulo que se incluye en su controlador, entonces también debe extender el módulo con ActiveSupport::Concern. Alternativamente, puede usar el gancho self.included para incluir ActionController::Live directamente en el controlador una vez que se incluya StreamingSupport.

Esto significa que si su aplicación solía tener su propio módulo de transmisión, el siguiente código se rompería en producción:

# Esta es una solución para controladores transmitidos que realizan autenticación con Warden/Devise.
# Consulte https://github.com/plataformatec/devise/issues/2332
# La autenticación en el enrutador es otra solución como se sugi

Comentarios

Se te anima a ayudar a mejorar la calidad de esta guía.

Por favor contribuye si ves algún error tipográfico o errores fácticos. Para comenzar, puedes leer nuestra sección de contribuciones a la documentación.

También puedes encontrar contenido incompleto o cosas que no están actualizadas. Por favor agrega cualquier documentación faltante para main. Asegúrate de revisar Guías Edge primero para verificar si los problemas ya están resueltos o no en la rama principal. Revisa las Guías de Ruby on Rails para estilo y convenciones.

Si por alguna razón detectas algo que corregir pero no puedes hacerlo tú mismo, por favor abre un issue.

Y por último, pero no menos importante, cualquier tipo de discusión sobre la documentación de Ruby on Rails es muy bienvenida en el Foro oficial de Ruby on Rails.