@drawoharai ❤️ this! << haz clic aquí 🐛 🫖 🧚
/dangling-rpc-fruit-off-of-your-rails-controllers
publicado en: 2013-11-05

Cuando se trabaja en cualquier aplicación de Rails que no sea un simple "Hola mundo", inevitablemente se necesitan pequeños ayudantes AJAX para comunicarse con el servidor y realizar lógica del lado del cliente. No me refiero a una API en sí, sino a utilidades ad-hoc como esta:

markdown.change(function(){
  generate_html_on_the_server( markdown.val(), function(html){
  
    preview.html(html);
  
  });
});

o

reservation.change(function(){
  check_availibity_on_the_server( reservation.val(), function(data){
  
    if(!data['available']){
     
     alert('ese tiempo no está disponible - elige otro!');
     
    };
  })
});

etc.

Este tipo de funciones no forman parte de una API pública de servidor a servidor, son simplemente puntos finales de cooperación js/backend que son necesarios para que funcione la vista.

La mayoría de las aplicaciones de Rails acumularán muchas de estas y surge la pregunta:

“¿Dónde las pones?”

En la mayoría de los equipos, tendrás tres o cuatro desarrolladores nombrando y organizando estas funciones de diferentes maneras, asegurando que la base de código se convierta en un desorden de espagueti vaquero en poco tiempo.

@dojo4 hemos abstraído esto con un pequeño patrón de diseño rpc: primero tenemos un pequeño dsl de controlador que se incluye en nuestro ApplicationController que permite definiciones declarativas de ayudantes js 'rpc' por controlador.

class ApplicationController < ActionController::Base
  include(RPC)
end

Consulta la implementación aquí: https://gist.github.com/ahoward/7320900

En inglés sencillo, este dsl simplemente define una única acción en el controlador que multiplexa qué método emplear en función de los parámetros y una forma fácil de definirlos. Espera que todas las acciones rpc devuelvan un hash y proporcionen json.

Su implementación se reduce a

  def rpc
    which = params['method']
    
    action = @rpc[which]
    
    result = action.call(params)
    
    render :json => result.to_json
  end

Su uso debería ser obvio a partir del código

class GeoLocationController < ApplicationController
  rpc(:geo_location) do |params|
    geo_location = GeoLocation.geo_locate( params['address'] )
    geo_location.attributes
  end
  
  rpc(:lat_lng) do |params|
   geo_location = GeoLocation.geo_locate( params['address'] )
   { 'lat' => geo_location.lat, 'lng' => geo_location.lng }
  end