Rails Upgrade
Actualización de Rails 6.1.7 a Rails 7.0 en una aplicación tipo API.
Antes de la actualización las especificaciones son:
- Tengo un Mac M1 MacOs ventura
- Rails 6.1.7
- Ruby 2.7.3
- Cliente para el mac PostgreSQL 13.0
- Redis server 6.2.4
Paso a paso de la actualización:
- Hay una recomendación respecto a no actualizar de una versión muy antigua a una muy reciente, por ejemplo, no es recomendable actualizar de Rails 5 a Rails 7, en este caso no aplica, ya que estamos pasando de 6.1 a 7 lo cual está bien.
- Copiar y pegar nuestro Gemfile.lock en RailsBumb para poder revisar cuáles de nuestras gemas nos van a generar errores o problemas.
- Usar la gema “next_rails” para revisar cuáles gemas tenemos que actualizar, cuando ya la tengamos instalada solo haremos un
bundle_report compatibility --rails-version=version_deseada
, después de esto ya podemos actualizar las gemas que nos aparezcan en el reporte. - Actualización de gemas:
- Si el reporte nos pide actualizar gemas que hacen parte de Rails como
ActionMailer
oActionText
estas se van a actualizar con el cambio de versión a Rails 7. Si las gemas son instaladas por nosotros, obviamente debemos hacer la actualización. - No es aconsejable tener una versión fija de una gema en nuestro
Gemfile
así que es un buen momento para ir eliminando eso.
- Si el reporte nos pide actualizar gemas que hacen parte de Rails como
- Luego de actualizar las gemas ahora podemos en nuestro
Gemfile
actualizar la versión de Rails y correrbundle update
. - Cuando se haga la actualización lo primero es cambiar el
load_defaults
a Rails 7 en nuestro archivoconfig/application.rb
. - En mi caso uso
Spring
esta gema está en su versión 2.1.1 por alguna razónnext-rails
no la tuvo en cuenta, pero debe ser actualizada a una versión3X
.- Cuando intenté actualizar la gema me decía que no podía porque estaba bloqueada, para esto lo que hice fue eliminar mi Gemfile.lock.
- Luego en
config/environments/test.rb
lo dejé configurado enfalse
.
- Configurar
Zeitwerk
.-
Zeitwerk
es la única forma en Rails 7 para cargar de forma segura archivos y evitar el uso excesivo derequire
. - Como ya se hizo el cambio a Rails 7 en la aplicación en
config/application.rb
se debe eliminar la líneaconfig.autoloader
. - Verificar si ya está corriendo todo bien con
bin/rails runner 'p Rails.autoloaders.zeitwerk_enabled?'
debe retornartrue
o en su defecto los respectivos warnings.
-
- Encriptación
- En este punto, al iniciar el server estaba obteniendo un error
ActiveSupport::MessageEncryptor::InvalidMessage
esto es por la encriptación. - En la API se encripta los atributos siguiendo este tutorial, pero al actualizar Rails la encriptación cambia, porque Rails 7 usa SHA256 mientras que en las versiones anteriores se usa SHA1, pero este protocolo está obsoleto, para solucionar esto se debe especificar que siga encriptando con SHA1 mientras que luego se hace la el cambio para poder usar los atributos encriptados de Rails 7, para solucionarlo me funcionó agregar el
hash_digest_class
así:
- En este punto, al iniciar el server estaba obteniendo un error
class EncryptionService
KEY = ActiveSupport::KeyGenerator.new(
Rails.application.credentials[:secret_key_base],
hash_digest_class: OpenSSL::Digest::SHA1
).generate_key(
Rails.application.credentials[:ENCRYPTION_SERVICE_SALT],
ActiveSupport::MessageEncryptor.key_len
).freeze
- Al correr los test encontré el error
RuntimeError: Foreign key violations found in your fixture data
, esto se debe a que en versiones anteriores se podían tenerfixtures
con unamissing association
, esto ya no será posible en Rails 7.- Una opción es en
application.rb
agregar la líneaconfig.active_record.verify_foreign_keys_for_fixtures = false
. - La otra opción es arreglar los errores en los fixtures(Lo cual es lo recomendado), para detectar qué tablas tenemos mal, primero reseteamos y cargamos la base datos de test para luego entrar en la consola así:
- Una opción es en
RAILS_ENV=test bin/rails db:reset
RAILS_ENV=test bin/rails db:fixtures:load
RAILS_ENV=test bin/rails c
- Luego corremos esta consulta para identificar si hay tablas que les falta una asociación para poder corregir los
fixtures
y ya con esto el error se solucionará:
ActiveRecord::Base.connection.execute(<<~SQL)
do $$
declare r record;
BEGIN
FOR r IN (
SELECT FORMAT(
'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I''; ALTER TABLE %I VALIDATE CONSTRAINT %I;',
constraint_name,
table_name,
constraint_name
) AS constraint_check
FROM information_schema.table_constraints WHERE constraint_type = 'FOREIGN KEY'
)
LOOP
EXECUTE (r.constraint_check);
END LOOP;
END;
$$;
SQL
- El siguiente error a corregir fue
ActionDispatch::Request::Session::DisabledSessionError: Your application has sessions disabled. To write to the session you must first configure a session store
:- En
config/application.rb
tenía la líneaconfig.middleware.use ActionDispatch::Cookies
para solucionar me funcionó esta respuesta de este hilo
- En
Este fue todo el proceso en mi caso, las guías y documentos de apoyo para esta actualización fueron:
Top comments (0)