No soy un desarrollador que se considere serior ni nada parecido, solo tengo cierta experiencia en algunos frameworks web, sobre todo con Ruby on Rails y cuando el cliente así lo demandaba, AngularJS y React. Donde me siento un "desarrollador feliz" es en Rails, un tanto por las bondades de ruby, otro tanto por la forma de trabajar de Rails. Pero debo admitir que la reactividad era algo engorroso de lograr sin caer en las mixturas y aunque últimamente salieron grandes intentos de la comunidad como Stimulus Reflex (a los que aplaudo y agradezco inmenzamente por sus aportes y esfuerzos por hacer del Universo Rails un mejor lugar) siempre me quedaba la sensación de que si bien se iba mejorando el cómo trabajar la reactividad aún faltaba un ajuste de tuerca. Es por eso que me puso muy contento encontrar esta gema, un gran trabajo de la gente de Motion. Gracias totales a ellos y a toda la comunidad.
La promeza de Motion es muy atractiva "Motion allows you to build reactive, real-time frontend UI components in your Rails application using pure Ruby."
Poder ser reactivos en Rails escribiendo 100% código ruby y no dejar de ser Rails en el intento, para mi no tiene precio. Quería aclarar que no tengo nada en contra de JS y todo su ecosistema, es sólo una alegría poder trabajar con el lenguage que me hace sentir mas cómodo.
Instalarla es muy sencillo y solo hay que seguir los pasos que ellos detallan en su repositorio así que no voy a detenerme en eso, salvo para comentar que se apoyan en otro gran desarrollo como es ViewComponent una gema de la gente de Github que va a estar en el core de Rails desde la version 6.1.
Esta combinación es ganadora, componentes reactivos!
Veamos un ejemplo extraído de su documentación:
El Hola mundo de la reactividad, un boton contador reactivo!
Al instalar Motion tenemos disponible un generador para
rails g motion:component <component-name>
Vamos a correr este comando que nos generará nuestro componente. Veremos como nos crea una carpeta "components" y dentro de ella nuestros archivos "button_component.rb" donde va a estar nuestra lógica de componente y "button_component.html.erb" donde estará nuestro HTML
> rails g motion:component button
Running via Spring preloader in process 21091
generate component
rails generate component Button
Running via Spring preloader in process 21096
create app/components/button_component.rb
invoke test_unit
identical test/components/button_component_test.rb
invoke erb
create app/components/button_component.html.erb
insert app/components/button_component.rb
podemos renderizar nuestro componente en cualquier vista que tengamos usando la siguiente linea
<%= render ButtonComponent.new %>
Pongamos un poco de lógica reactiva a nuestro componente
class ButtonComponent < ViewComponent::Base
include Motion::Component
attr_reader :total
def initialize(total: 0)
@total = total
end
map_motion :add
def add
@total += 1
end
end
lo importante de aquí es el map_motion :add
que va a ser la unión entre nuestro componente HTML y el método en nuestro componente ruby
yo estoy usando Bulma para esta prueba pero puedes usar cualquier framework CSS o incluso ninguno.
Agreguemos nuestro HTML al componente
<div>
<span><%= total %></span>
<%= button_tag "Increment", data: { motion: "add" }, class: "button is-small is-info" %>
</div>
Dos cosas para destacar aquí:
Una limitación es, que todo en nuestro template del componente debe tener un nodo principal, en nuestro caso envolvemos todo con un simple div, esto es por como funciona Motion por detrás, muy similar a cómo trabaja React.
La otra cosa para destacar es ´data: { motion: "add" }´ es la conección con nuestro componente en ruby, es lo que va a disparar el metodo con el mismo nombre.
Y eso es todo lo que necesitamos, con eso deberíamos tener un boton reactivo completamente funcional y sin escribir una linea de javascript.
Otro pequeño ejemplo es el clásico escribo y reacciono, nuestro código podría ser algo como esto:
<div>
<p>My name is <%= name %> <%= 'ok!' if @is_ok %></p>
<input type="text" data-motion="keyup->update" class="input">
</div>
class InputComponent < ViewComponent::Base
include Motion::Component
attr_reader :name
def initialize(name: "")
@name = name
end
map_motion :update
def update(event)
new_value = event.current_target.value
@name = new_value
@is_ok = new_value == "sebastián"
end
end
Otras dos cosas para destacar aquí.
Por defecto motion tomará como trigger en input el evento change pero podemos definir qué evento bindear, como se ve en el ejemplo ´data-motion="keyup->update"´ estamos bindeando keyup
Otro aspecto interesante es que nuestro método en ruby recibe un ´event´ como parámetro, donde tenemos disponible datos como el current_target para obtener su valor (en este ejemplo) o poder acceder a sus atributos, etc..
Imaginen el potencial de esto usando ActiveRecord, CableReady, chartkick, etc...
Gracias por llegar hasta aquí. Esto no pretende ser un tutorial o una introducción a Motion, solo era compartir con ustedes esta herramienta que seguramente va a pasar a ser cotidiana en mi trabajo.
Dios los bendiga!
Top comments (0)