Una nueva mirada al desarrollo de Fullstack con el marco Ruby on Rails

¿Es posible discutir seriamente el desarrollo completo? Si mira hacia marcos grandes para el frontend y el backend, entonces hablar de fullstack parece dudoso. Sugiero mirar el término fullstackdesde el punto de vista de Ruby on Rails y los principios más simples anteriores de implementar la interactividad en las páginas web clásicas. Le presento una descripción general de las funciones frontend proporcionadas en el marco de Ruby on Rails o relacionadas con él.

imagen


Ruby on Rails es un marco MVC que se centra en el desarrollo rápido y presta mucha atención a mantener la coherencia dentro de un proyecto (para que no resulte "de todos modos" "rápidamente"). Proporciona muchas herramientas para el desarrollo de backend y frontend. En la dirección clásica de fullstack, hubo una omisión momentánea debido a la ignorancia de su desarrollo y la idea errónea sobre el retraso de los fondos usados. El objetivo de este artículo es resaltar cómo se desarrolla el enfoque fullstack y cuántas posibilidades interesantes diferentes han aparecido en él.

Webpacker


Webpacker es una gema que se envía con Ruby on Rails.

Webpacker proporciona un contenedor sobre Webpack: comandos para conectar e iniciar configuraciones para el trabajo. Webpacker establece de facto el estándar para trabajar con frontend en Ruby on Rails, promueve el uso de las últimas funciones de JavaScript y los principios modernos de trabajar con código (estructura, modularidad, ensamblaje y mucho más).

Webpacker define las configuraciones generales necesarias para comenzar y la estructura de la aplicación, lo que aumenta la certeza y simplifica la comprensión del proyecto por parte de diferentes desarrolladores. Para el código JavaScript, se asigna la carpeta app/javascript/con el archivo primario app/javascript/packs/application.js.

Archivos y carpetas añadidos por Webpacker
config/webpacker.yml
config/webpack/
config/webpack/development.js
config/webpack/environment.js
config/webpack/production.js
config/webpack/test.js
package.json
postcss.config.js
babel.config.js
.browserslistrc
node_modules/
bin/webpack
bin/webpack-dev-server
app/javascript/
app/javascript/packs/
app/javascript/packs/application.js


Webpacker se inicia por defecto durante el proceso de creación de una nueva aplicación y realiza su configuración. Puede crear la aplicación de inmediato con configuraciones adicionales para Stimulus, Vue, Typecript u otra de la lista proporcionada :

rails new myapp --webpack=stimulus

O instale configuraciones adicionales después de crear la aplicación:

bundle exec rails webpacker:install:stimulus

Desarrolle Frontend con el marco Ruby on Rails = use los enfoques de desarrollo de JavaScript más actuales. Toda la conveniencia de usar los estándares modernos de JavaScript están bien integrados con Ruby on Rails. Se proporcionan las configuraciones necesarias para trabajar con Webpack, lo que le permite estar menos distraído por la organización correcta del proyecto y centrarse en resolver tareas populares utilizando el entorno familiar.

Turbolinks


Turbolinks es la biblioteca de JavaScript que se incluye con Ruby on Rails.

La tarea prioritaria de Turbolinks es facilitar la carga en el servidor y reducir las "costuras" al navegar a las URL de las aplicaciones. Esta característica a menudo se compara con SPA, ya que da la impresión de una nueva representación del contenido en el navegador en lugar de transiciones simples entre páginas.

Principio de funcionamiento de Turbolinks: para navegar entre páginas no mediante una transición estándar a una nueva dirección, sino cumpliendo una solicitud a esta dirección "en segundo plano" a través de ajax, cargando la respuesta en JavaScript y reemplazando el contenido de la página por una nueva. Este proceso se acompaña de eventos especiales que le permiten agregar funcionalidad a la transición entre páginas y volver a las páginas anteriores. Por ejemplo,
  • para iniciar la transición hacia una dirección diferente: turbolinks:click, turbolinks:before-visit, turbolinks:visit;
  • o el procesamiento de una solicitud de una nueva página turbolinks:request-start, turbolinks:request-end:;
  • o en el proceso de mostrar una nueva página turbolinks:before-render, turbolinks:render, turbolinks:load.

Además, Turbolinks tiene una barra de progreso, almacena en caché el historial de páginas cargadas y le permite especificar elementos de página no actualizados.

Cable de acción


ActionCable es parte del marco de Ruby on Rails. ActionCable hace que trabajar con sockets web. Para una lista de canales en el servidor, una carpeta app/channels/con los archivos principales channel.rby está provisto connection.rb. Para implementar la conexión a estos canales: una carpeta app/javascript/channels/con archivos index.jsy consumer.js.

Es mejor familiarizarse con las posibilidades de ActionCable de inmediato con un ejemplo. La conexión más simple a los sockets web con su ayuda se puede implementar en solo un par de pasos.

  1. Crear archivo de canal

    app / canales / hello_channel.rb
    # app/channels/hello_channel.rb
    class HelloChannel < ApplicationCable::Channel
      def subscribed
        stream_from "hello_1"
      end
    end
    

  2. Crea una suscripción a este canal
    aplicación / javascript / canales / hello_channel.js
    // app/javascript/channels/hello_channel.js
    import consumer from "./consumer"
    
    consumer.subscriptions.create({ channel: "HelloChannel" }, {
      received(data) {
        console.log("Data received", data);
        document.body.innerText += `\nHello, ${data.name}!`
      }
    })
    


Y la conexión a los enchufes web está lista.

Ahora, para verificarlo, necesitamos una página simple y una acción para enviar. Para hacer esto, cree un controlador y agregue sus direcciones a las rutas

app / controllers / hello_controller.rb
# app/controllers/hello_controller.rb
class HelloController < ApplicationController
  def index
    render :html => "Hello page...", :layout => true
  end

  def new
    ActionCable.server.broadcast("hello_1", name: params[:name])
    head 200
  end
end


config / routes.rb
# config/routes.rb
get "/hello" => "hello#index"
get "/hello/new" => "hello#new"


Iniciamos la aplicación, vamos a la dirección 127.0.0.1haps000 / hello y abrimos la consola del navegador, en ella puedes ver el registro de mensajes que provienen del servidor a través de sockets web.

A continuación, enviamos una solicitud de envío de acciones:

curl http://127.0.0.1:3000/hello/new?name=World

Y mira la página / hello y la salida en su consola.

Ayudantes de forma y Rails-ujs


Cabe destacar algunas características no nuevas, pero bien establecidas del marco de Ruby on Rails. Entre ellos hay ayudantes para representaciones y formas. La conveniencia inicial de los ayudantes es que facilitan la integración del marcado con modelos, configuraciones y otros componentes de back-end. La ventaja de los ayudantes de formulario sobre el marcado convencional es la capacidad de enumerar rápidamente los campos de formulario sin entrar en los detalles de su enlace a los atributos del modelo: al usar ayudantes, la relación entre ellos se formará automáticamente. Un fragmento que muestra un ejemplo de campos de formulario de enlace con parámetros de controlador y atributos de modelo:

app / views / articles / new.html.erb
<%# app/views/articles/new.html.erb %>
<%#      %>
<%= form_with(model: Article.new) do |f| %>
  <div>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.label :text %>
    <%= f.text_area :text %>
  </div>
  <%= f.submit %>
<% end %>


config / locales / ru.yml
# config/locales/ru.yml
#       
ru:
  activerecord:
    attributes:
      article:
        title:  
        text:  


config / application.rb
# config/application.rb
#        config/application.rb
config.i18n.default_locale = :ru


app / controllers / articles_controller.rb
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController

  def new
    #  new   
    # rails -     
  end

  def create
    #        
    @article = Article.create(article_params)

    #    -    ,
    #    url  
    #   ,   
    redirect_to @article
  end

  private

  def article_params
    #      
    params.require(:article).permit(:title, :text)
  end
end


Puede obtener más información sobre este ejemplo aquí y aquí .

Rails-ujs


Rails-ujs es la parte central del marco de Ruby on Rails para JavaScript discreto.
Rails-ujs proporciona varias opciones adicionales para elementos de página que cambian o expanden su forma de trabajar.

Opción remota: diseñada para elementos que acceden al servidor (enlaces, formularios) para realizar solicitudes asincrónicas. Ejemplo de enlace:

<%= link_to " ", new_article_path, remote: true %>

Para mostrar los resultados de esta consulta requiere manipulación adicional, por ejemplo, la adición de manejador de eventos remotos-: ajax:success, ajax:error, ajax:complete.

La opción de confirmación: le permite solicitar la confirmación de la acción antes de que se ejecute.

<%= link_to "", article_path(article), method: :delete,
  data: { confirm: ' ,     ?' } %>


Opción Disable_with: le permite desactivar un elemento después de una acción.
<%= form.submit data: { disable_with: "..." } %>

Además, Rails-ujs tiene varias características útiles. Estos son algunos de ellos:

Rails.fire(obj, name, data)- función de llamada de evento
Rails.ajax(options)- contenedor sobre XMLHttpRequest
Rails.isCrossDomain(url)- verificación de url perteneciente a otro dominio
Rails.$(selector)- contenedor sobre document.querySelectorAll Puede

conectarlos a su código con el comando

import Rails from "@rails/ujs"

Estímulo


Estímulo: marco de JavaScript de los desarrolladores de Ruby on Rails.

Stimulus es uno de los marcos raros y único a su manera, ya que implementa el desarrollo frontend utilizando nuevos enfoques de JavaScript, mientras que no busca controlar todas sus acciones y no impone una separación del frontend del backend.

La tarea básica de Stimulus es vincular manejadores a eventos. Según Stimulus, el código fuente debe colocarse en clases de controlador y sus métodos deben usarse como controladores. Por defecto, la carpeta app/javascript/controllers/con el archivo primario se asigna a los controladores de estímulo en el proyecto index.js. Aquí podemos agregar nuestros controladores, para esto necesitamos crear un archivo con un sufijo _controller.js, por ejemplo,articles_controller.js. A continuación, el cargador de estímulo importa dichos archivos y conecta los controladores a los bloques correspondientes en nuestras páginas.

Los controladores en Stimulus tienen equipo adicional: inicialización del objeto controlador ( initialize), ayudantes para acceder a elementos dentro del bloque ( targets, objetivos), adjuntar el objeto controlador al bloque ( connect) y desconectarse de él ( disconnect), acceder a los atributos de datos del bloque ( this.data.get). El siguiente es un ejemplo de un bloque de estado activo / inactivo escrito en Estímulo.

app / views / home / show.html.erb
<%# app/views/home/show.html.erb %>

<%#   home   %>
<%#      (  ) %>
<div data-controller="home"
    data-home-active-text="Activated" data-home-deactive-text="Deactivated">

  <%#    text  home  %>
  <p data-target="home.text"></p>

  <%#   action click  home %>
  <button data-action="home#click"></button>

</div>



app / javascript / controllers / home_controller.js
// app/javascript/controllers/home_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  //  
  static targets = [ "text" ]

  initialize() {
    //      
    this.activeText = this.data.get("active-text");
    this.deactiveText = this.data.get("deactive-text");
  }

  connect() {
    //   /
    this.active = this.data.get("active") == "true";
    //  
    this.refresh();
  }

  disconnect() {
    //     
    this.element.setAttribute("data-home-active", !!this.active);
  }

  click() {
    //  
    this.active = !this.active;
    //  
    this.refresh();
  }

  //    
  refresh(){
    //     
    this.element.style.background =   this.active ? "none" : "#EEE";
    //  
    this.textTarget.innerHTML =   this.active ? this.activeText : this.deactiveText;
    //   
    this.textTarget.style.color = this.active ? "black" : "#777";
  }
}


A pesar de mantener los viejos principios para implementar la funcionalidad interactiva en las páginas clásicas, el enfoque de desarrollo con Stimulus se mejora significativamente: la estructura del código fuente se estructura de una nueva manera, se cambia la vinculación de los controladores a los eventos y se proporciona equipo adicional. Gracias a estas comodidades y su simplicidad, el marco Stimulus le permite estructurar de manera rápida y competente incluso una gran interfaz.

Además, vale la pena enfatizar que Stimulus combina bien con otras características de Ruby on Rails: la aparición útil aparece en casi todos los paquetes.

Estímulo y Webpacker


Webpacker proporciona comandos para crear una aplicación con un estímulo conectado:

rails new myapp --webpack=stimulus

O para conectarlo a un proyecto ya creado:

bundle exec rails webpacker:install:stimulus

Estímulo y JavaScript


Stimulus promueve el uso de principios modernos de desarrollo de JavaScript para implementar la interactividad en sus páginas. Con Stimulus, la solución frontend se construye de forma modular, se utiliza OOP para los controladores de eventos y el código está estructurado cuidadosamente. Con la herramienta de orientación, con controladores de estímulo, es conveniente controlar la conexión a los elementos de bloque de componentes gráficos complejos tomados de bibliotecas de terceros o escritos de forma independiente (calendarios, compiladores automáticos, listas, árboles y otros). Gracias a esto, Stimulus es una de las formas más sencillas de cambiar de herramientas frontend obsoletas y obtener la productividad necesaria del uso de JavaScript puro moderno.

Estímulo y rubí sobre rieles


Con la estructura de código recomendada por Stimulus, continúa escribiendo en JavaScript de la misma manera que lo haría en Ruby on Rails. También declara controladores, también vincula acciones a métodos. Con Stimulus, el desarrollo frontend se vuelve similar al backend, lo que facilita el trabajo tanto allí como allí.

Estímulo y ActionCable


Utilizando los métodos de inicialización y conexión en los controladores de estímulo, es conveniente vincular los sockets web no a toda la página, sino a sus bloques individuales y trabajar con precisión con los mensajes entrantes. Cada vez es más fácil organizar varias transmisiones paralelas en una página con cambio de canal independiente.

Estímulo y Turbolinks


Stimulus se activa tan pronto como Turbolinks carga la página; no se necesitan manipulaciones adicionales para conectar Stimulus a los bloques de la página.

Turbolinks no solo facilita la carga de páginas, sino que también almacena en caché su contenido durante la transición. Cuando regresa a la página en caché desde el historial, Stimulus se activa automáticamente, como al cargar una nueva página. Si desea guardar algunos valores antes de desconectar el controlador de la unidad, puede usar el método disconnect, y luego, al regresar y conectar el controlador, podrá restaurar su último estado. En el código del primer ejemplo de trabajo con Estímulo, puede ver cómo, al desconectar ( disconnect), el valor se fija en el atributo de datos del bloque controlador this.active, y al conectar ( connect), se extrae de nuevo.

Volver a través de las páginas puede ser una forma útil de trabajar con la aplicación. Por ejemplo, cuando se trabaja con un formulario, puede ser necesario completar / editar el valor en el directorio en otra página, luego regresar y seleccionar nuevos datos.

Otro ejemplo: supongamos que necesitamos editar o ver los valores en la página de configuración del chat web. Cuando desconectemos el controlador de la unidad con la conversación, será útil para nosotros recordar el identificador del último mensaje, así que al regresar, primero solicite los mensajes nuevos que faltan y luego abra la conexión a través de los enchufes web.

Por lo tanto, un historial de retorno en la página se puede utilizar como una forma conveniente de trabajar con su aplicación web.

Estímulo y formas de ayuda


Stimulus trabaja en estrecha colaboración con el marcado, y con la ayuda de ayudantes, los datos se incrustan fácilmente en bloques html, gracias a esto, parte de los datos pueden cargarse en el atributo de datos del bloque y entregarse al controlador.

app / views / articles / show.html.erb
<%#       app/views/articles/show.html.erb %>

<%#      %>
<% article_data = article.attributes
      .slice("id", "created_at", "updated_at", "author", "title").to_json %>

<%#   div    content_tag %>
<%= content_tag :div,
    :data => { controller: :articles },
    "data-articles-attributes" => article_data do %>
  <%# ... %>
<% end %>


app / javascript / controllers / articles_controller.js (fragmento)
//   
//   initialize  app/javascript/controllers/articles_controller.js
initialize() {
  this.attributes = JSON.parse(this.data.get("attributes"));
  //   
  // ...
}


Estímulo y rieles-ujs


Usando Stimulus y las opciones remotas, puede conectar directamente los controladores a eventos ajax y procesar los resultados de la consulta. Declare el enlace usando Rails-ujs y adjúntele un controlador de estímulo.

enlace con opción remota y manejador de estímulo
<%= link_to " ",
  article_path(article, format: :html),
  data: { remote: true, action: "ajax:success->articles#showArticle" } %>


Cuando hace clic en este enlace, se producirá una solicitud asíncrona de Ajax al controlador de rieles articles_controller.rbpara la acción de mostrar. Al recibir una respuesta positiva, se disparará un evento y se llamará ajax:successal método showArticledel controladorapp/javascript/controllers/articles_controller.js

controlador showArticle method app / javascript / controllers / articles_controller.js
showArticle(e) {

  //      
  const xhr = e.detail[2];

  //    
  this.showFormTarget.innerHTML = xhr.responseText;

  //  
  this.showFormTarget.style.display = "block";
}


¿Que sigue?


Estas herramientas, junto con el marco de Ruby on Rails, abren nuevos horizontes para el desarrollo completo. Además, las herramientas descritas son relativamente simples y no requieren inmersiones largas: todo lo necesario para un proyecto exitoso está en la superficie.

¡Cree aplicaciones web con herramientas modernas y rápidas de desarrollo fullstack con el marco Ruby on Rails y disfrútelo!

All Articles