DEV Community

Jairo Andrés Orjuela
Jairo Andrés Orjuela

Posted on

Update Rails 6.1 a Rails 7

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 o ActionText 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.
  • Luego de actualizar las gemas ahora podemos en nuestro Gemfile actualizar la versión de Rails y correr bundle update.
  • Cuando se haga la actualización lo primero es cambiar el load_defaults a Rails 7 en nuestro archivo config/application.rb.
  • En mi caso uso Spring esta gema está en su versión 2.1.1 por alguna razón next-rails no la tuvo en cuenta, pero debe ser actualizada a una versión 3X.
    • 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 en false.
  • Configurar Zeitwerk.
    • Zeitwerk es la única forma en Rails 7 para cargar de forma segura archivos y evitar el uso excesivo de require.
    • Como ya se hizo el cambio a Rails 7 en la aplicación en config/application.rb se debe eliminar la línea config.autoloader.
    • Verificar si ya está corriendo todo bien con bin/rails runner 'p Rails.autoloaders.zeitwerk_enabled?' debe retornar true 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í:
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
Enter fullscreen mode Exit fullscreen mode
  • 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 tener fixtures con una missing association, esto ya no será posible en Rails 7.
    • Una opción es en application.rb agregar la línea config.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í:
RAILS_ENV=test bin/rails db:reset
RAILS_ENV=test bin/rails db:fixtures:load
RAILS_ENV=test bin/rails c 
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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ínea config.middleware.use ActionDispatch::Cookies para solucionar me funcionó esta respuesta de este hilo

Github Response

Este fue todo el proceso en mi caso, las guías y documentos de apoyo para esta actualización fueron:

Latest comments (0)