Características de Rails 6: Novedades y por qué es importante
Publicado: 2022-03-11Como la mayoría de los fanáticos de Ruby on Rails sabrán, Rails 6 llegará pronto y traerá una serie de características y cambios muy esperados. El objetivo de este artículo es familiarizarlo con las características clave que se agregaron a Rails 6 y describir cómo pueden ayudarlo a mejorar sus aplicaciones, ahorrando así un valioso tiempo de desarrollo.
Para empezar, recuerda que Rails 6 requiere Ruby 2.5+ y bases de datos actualizadas. Por lo tanto, asegúrese de tener un plan para actualizar sus sistemas en consecuencia, en caso de que aún no lo haya hecho.
Entonces, ¿cuáles son estas nuevas características? Aquí hay un resumen rápido de las funciones clave de Rails 6 que probablemente usará en el futuro:
Pruebas en Rails 6
Como desarrolladores profesionales de Ruby on Rails, nuestro objetivo es garantizar la máxima cobertura para nuestro código. Sin embargo, las pruebas se vuelven una actividad tediosa cuando nuestros casos de prueba se vuelven "pesados" y tenemos que esperar varios minutos, o incluso horas, solo para ejecutar los casos de prueba.
Pruebas paralelas
Bueno, Rails 6 tiene una respuesta aquí. Ha agregado un método de parallelize
a ActiveSupport::TestCase
que le permite paralelizar el conjunto de pruebas con procesos bifurcados.
Entonces, lo que debe hacer para paralelizar los procesos para sus pruebas es agregar esto a su test_helper.rb
:
parallelize(workers: 2)
Alternativamente, podemos reemplazar nuestros comandos utilizados anteriormente para ejecutar pruebas. Por ejemplo, bin/rails test OR bin/rspec spec
ahora se puede reemplazar por PARALLEL_WORKERS=15 rails test OR PARALLEL_WORKERS=15 rspec spec
.
En consecuencia, puede cambiar los comandos para ejecutar los conjuntos de pruebas en diferentes plataformas de CI como Travis, Gitlab, CircleCI y otras.
También hay ganchos cuando se crea/destruye cada proceso, que se pueden usar de la siguiente manera:
class ActiveSupport::TestCase parallelize_setup do |worker| # setup databases end parallelize_teardown do |worker| # cleanup databases end parallelize(workers: :number_of_processors) end
Nota: si desea obtener más información, puede consultar las Guías de Rails para obtener detalles adicionales.
Prueba de cable de acción
Ya que hablábamos de pruebas eficientes, entendamos también cómo ha mejorado Action Cable, una de las características más destacadas de Rails 5. Ahora es posible probar Action Cable a cualquier nivel: conexiones , canales y transmisiones .
Las pruebas de conexión tienen como objetivo verificar si los identificadores de una conexión se asignan correctamente o si se rechazan las solicitudes de conexión incorrectas:
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase test "connects with params" do connect params: { user_id: 42 } OR cookies.signed[:user_id] = "42" connect assert_equal connection.user_id, "42" end test "rejects connection without params" do assert_reject_connection { connect } end end
Se pueden escribir pruebas de canal para verificar si los usuarios pueden suscribirse a los canales y si el canal tiene una transmisión:
class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes and stream for room" do # Simulate a subscription creation by calling `subscribe` subscribe room: "15" # You can access the Channel object via `subscription` in tests assert subscription.confirmed? assert_has_stream "chat_15" end end
La transmisión a los canales se puede probar de esta manera:
# app/jobs/chat_relay_job.rb class ChatRelayJob < ApplicationJob def perform_later(room, message) ChatChannel.broadcast_to room, text: message end end # test/jobs/chat_relay_job_test.rb require 'test_helper' class ChatRelayJobTest < ActiveJob::TestCase include ActionCable::TestHelper test "broadcast message to room" do room = rooms(:all) assert_broadcast_on(ChatChannel.broadcasting_for(room), text: "Hi!") do ChatRelayJob.perform_now(room, "Hi!") end end end
Nota: Puede encontrar más consejos sobre cómo realizar la prueba aquí.
Inserción masiva y Upsert
En algún momento, todos necesitamos insertar varios registros de una sola vez y hemos encontrado muchas soluciones al hacerlo. Bueno, Rails 6 viene con un nuevo método listo para usar: insert_all
, similar a update_all
.
No activará ninguna devolución de llamada y ejecutará una única consulta SQL. Hay un método adicional upsert_all
que le permite usar la operación upsert que está expuesta en muchas bases de datos modernas como Postgres. Así que ahora puede reducir sus consultas de inserción y hacer que su código esté más optimizado. Además, diga adiós a las gemas utilizadas anteriormente como activerecord-import
.
Estos métodos preparan una sola consulta INSERT
SQL y se envía una sola instrucción SQL a la base de datos, sin instanciar el modelo ni invocar devoluciones de llamada y validaciones de Active Record. También es posible definir criterios cuando se viola una clave principal: índices únicos o restricciones únicas con una opción para omitir o ejecutar consultas upsert.
A continuación se muestran algunos ejemplos:
result = Article.insert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, #...snip... ], returning: %w[ id title ], unique_by: :index_articles_on_title_and_author ) result = Article.upsert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, { id: 1, .... }, # duplicate 'id' here { id: 2, .... }, { id: 3, .... }, # duplicate 'title' and 'author' here { id: 4, .... }, { id: 5, .... }, # duplicate 'slug' here { id: 6, .... } ] )
Los métodos insert
, insert!
y upsert
son envoltorios alrededor de insert_all
, insert_all!
y upsert_all
, respectivamente.
Nota: hay un artículo muy bueno que analiza las consultas masivas con respecto a diferentes bases de datos. Si necesita información adicional, asegúrese de consultarla.
Cambiar entre varias bases de datos
Una de las características principales que muchas grandes aplicaciones apreciarán es esta: Rails 6 finalmente ha agregado soporte para múltiples bases de datos para su aplicación, integradas y listas para usar, ¡listas para usar!
Por supuesto, la elección del diseño sigue siendo suya, ya sea que desee dividir su aplicación en múltiples microservicios, cada uno con una base de datos separada, tomar una ruta monolítica o agregar varias réplicas de lectura para su aplicación.
Sin embargo, tener la capacidad de hacerlo de una manera tan fácil tiene el potencial de ahorrar mucho tiempo en el frente del desarrollo.
Entonces, así es como se verá su nuevo archivo database.yml
:
development: primary: database: my_primary_db user: root primary_replica: database: my_primary_db user: ro_user replica: true animals: database: my_animals_db user: root animals_replica database: my_animals_db user: ro_user replica: true
Aquí hay formas interesantes de especificar cómo cambiar a diferentes bases de datos:
class AnimalsModel < ApplicationRecord self.abstract_class = true connects_to database: { writing: :animals_primary, reading: :animals_replica } end class Dog < AnimalsModel # connected to both the animals_primary db for writing and the animals_replica for reading end
Aquí está la página oficial de GitHub, que también está muy bien documentada. Personalmente, también espero tener capacidades de fragmentación de bases de datos en futuras actualizaciones de Rails (algo como esto).
Buzón de acción
Otra característica interesante de Rails 6 es la adición de Action Mailbox, que agrega la capacidad de enrutar correos electrónicos entrantes al controlador como buzones de correo para procesarlos en Rails.
Action Mailbox presenta entradas para Mailgun, Mandrill, Matasellos y SendGrid. También puede manejar los correos electrónicos entrantes directamente a través de los ingresos integrados de Exim, Postfix y Qmail. Ahora, probablemente pueda imaginar los beneficios potenciales sin entrar en más detalles. Puede ser desde el procesamiento directo de correos desde una mesa de ayuda hasta la automatización de tickets de soporte: Rails 6 permite a los clientes responder directamente por correo electrónico y mucho, mucho más. El piso está abierto para que explore esta característica y proponga un enfoque que sea ideal para su aplicación.

Aquí hay un pequeño ejemplo para entender cómo usar Action Mailbox:
COMMENTS_REGEX = /^comment\+(.+)@example\.com/i # app/mailboxes/application_mailbox.rb class ApplicationMailbox < ActionMailbox::Base routing COMMENTS_REGEX => :comments end # app/mailboxes/comments_mailbox.rb class CommentsMailbox < ApplicationMailbox def process user = User.find_by(email: mail.from) post_uuid = COMMENTS_REGEX.match(mail.to)[1] post = Post.find_by(uuid: post_uuid) post.comments.create(user: user, content: mail.body) end end
Además, la nueva forma de configurar los correos electrónicos es la siguiente (tomando el ejemplo de Sendgrid):
# config/environments/production.rb config.action_mailbox.ingress = :sendgrid
Use rails credentials:edit
para agregar la contraseña a las credenciales cifradas de su aplicación en action_mailbox.ingress_password
, donde Action Mailbox la encontrará automáticamente:
action_mailbox: ingress_password: …
Configure SendGrid Inbound Parse para reenviar correos electrónicos entrantes a /rails/action_mailbox/sendgrid/inbound_emails
con el nombre de usuario actionmailbox
y la contraseña que generó anteriormente. Si su aplicación vive en https://example.com
, configuraría SendGrid con la siguiente URL:
https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/i
En caso de que quiera explorar esto más a fondo, Rails ya tiene una guía sobre esto aquí.
Zeitwerk
Zeitwerk es el nuevo cargador de código para Ruby. Dada una estructura de archivos convencional, Zeitwerk carga las clases y los módulos de su proyecto a pedido, lo que significa que no necesita escribir llamadas requeridas para sus propios archivos. Para habilitarlo en Rails 6, puede hacer lo siguiente:
config.autoloader = :zeitwerk
Puedes leer más sobre Zeitwerk aquí.
Sugerencias del optimizador
¿Le preocupa que algunas de sus consultas estén tardando demasiado en ejecutarse? Bueno, ahora también tiene una forma de definir tiempos de espera para sus consultas.
La siguiente declaración generará una excepción StatementTimeout
si la consulta tarda más de lo normal en ejecutarse:
User.optimizer_hints("MAX_EXECUTION_TIME(5000)").all
Es compatible con MySQL y tendrá que explorar si su base de datos lo admite.
Base de datos truncada
¿Qué pasa con la siembra de datos? La siguiente declaración truncará todas las tablas de su base de datos y luego podrá proceder a sembrar sus datos:
rails db:truncate_all
No más borrar sus bases de datos para sembrar. Probablemente estará de acuerdo en que esta es una solución elegante y rápida.
Texto de acción
Quizás otra característica notable para muchas aplicaciones que juegan con editores WYSIWYG es la adición de soporte para el editor Trix de forma nativa en las aplicaciones Rails 6. Esta será sin duda una buena actualización/adición para muchos proyectos.
La mayoría de los editores HTML WYSIWYG tienen un alcance enorme: la implementación de cada navegador tiene su propio conjunto de errores y peculiaridades, y los desarrolladores de JavaScript deben resolver las inconsistencias. Trix evita estas incoherencias al tratar contenteditable
como un dispositivo de E/S: cuando la entrada llega al editor, Trix convierte esa entrada en una operación de edición en su modelo de documento interno y luego vuelve a renderizar ese documento en el editor. Esto le da a Trix un control completo sobre lo que sucede después de cada pulsación de tecla.
Instalación:
rails action_text:install # app/models/message.rb class Message < ApplicationRecord has_rich_text :content end
Puede explorar Action Text con más detalle en la documentación oficial, aquí.
Seguridad
Ninguna actualización seria está completa sin algunas mejoras de seguridad. Rails 6 tampoco defrauda en el frente de la seguridad. La primera actualización de seguridad notable es la adición de soporte para Autorización de host .
La autorización de host es un nuevo middleware que protege contra los ataques de reenlace de DNS al permitir explícitamente a los hosts a los que se puede enviar una solicitud. Lo que esto significa es que puede definir los hosts que pueden acceder a sus aplicaciones.
Otra actualización de seguridad está destinada a frustrar los ataques que intentan copiar el valor firmado/cifrado de una cookie y utilizarlo como el valor de otra cookie. Lo hace ocultando el nombre de la cookie en el campo de propósito que luego se firma/cifra junto con el valor de la cookie. Luego, en la lectura del lado del servidor, verificamos los nombres de las cookies y descartamos las cookies atacadas. Habilite action_dispatch.use_cookies_with_metadata
para usar esta función, que escribe cookies con el nuevo propósito y los metadatos de caducidad incrustados.
Webpack como paquete predeterminado
Como es el estándar de facto con muchos marcos JavaScript modernos para el desarrollo front-end, Rails 6 ha agregado Webpack como el paquete de JavaScript predeterminado a través de la gema webpacker, reemplazando la canalización Rails Asset. Esta es una adición relativamente sencilla, y no entraremos en muchos detalles. Baste decir que Webpack brindará algo de alivio a los desarrolladores front-end con exceso de trabajo.
Prevención de condiciones de carrera
Rails 6 tiene un nuevo método que se utiliza para evitar condiciones de carrera SELECCIONAR/INSERTAR en nuestro código (estoy seguro de que muchos lectores han tenido la desgracia de encontrarse con condiciones de carrera a medida que escalan su proyecto). Aquí está el hilo de GitHub en caso de que necesite información adicional.
La tabla subyacente debe tener las columnas relevantes definidas con restricciones únicas. Si bien evitamos la condición de carrera entre SELECCIONAR → INSERTAR de #find_or_create_by
, en realidad tenemos otra condición de carrera entre INSERTAR → SELECCIONAR, que puede activarse si otro cliente ejecuta una ELIMINACIÓN entre esas dos declaraciones. Pero, para la mayoría de las aplicaciones, esa es una condición que es significativamente menos probable que alcancemos.
Credenciales en Rails 6
Desde los días de Rails 5.2, las credenciales han sido nombradas una nueva "forma de Rails" para manejar información confidencial con la promesa de deshacerse de los infames archivos .env de una vez por todas. Con las credenciales, las claves cifradas para servicios de terceros se pueden verificar directamente en el control de código fuente.
Sin embargo, hasta ahora, Rails usaba el mismo archivo cifrado para todos los entornos, lo que hacía que manejar diferentes claves en el desarrollo y la producción fuera un poco complicado, especialmente cuando se trata de grandes proyectos y código heredado.
En Rails 6, esto finalmente se resuelve con soporte para credenciales por entorno. Nuevamente, se pueden explorar más detalles en el hilo oficial de GitHub.
¿Rails 6 es una buena actualización?
Sí, y de hecho, Rails 6 podría describirse como una actualización importante, aunque pocos lo llamarían un cambio de juego. Dado que Ruby on Rails existe desde hace años, pocas personas esperan cambios revolucionarios, pero su sexta encarnación trae mucho a la mesa.
Algunas funciones implementadas en Rails 6 parecen mejoras menores, mientras que otras tienen el potencial de ahorrar mucho tiempo de desarrollo, mejorar la seguridad, la solidez, etc. En pocas palabras: Rails está maduro, muchos desarrolladores siguen entusiasmados con su futuro, y con el lanzamiento de Rails 6, se puso aún mejor.
Por supuesto, esta lista de características de Rails 6 está incompleta y para ver el conjunto completo de cambios, debe consultar el registro de cambios. Además, hay muchas deprecaciones que debe considerar. Finalmente, si insiste en revisar cada cambio y actualizarse, lea las notas completas de la versión.