Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. WordPress
Code

Desarrolla una API personalizada para conectar WordPress con Ruby on Rails

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by Steven (you can also view the original English article)

Final product image
What You'll Be Creating

Érase una vez, las aplicaciones web solían ser monolitos que hacían todo por sí mismas. Estos días, no tanto. Con los servicios web que abren sus API, los desarrolladores están optando por utilizar aplicaciones de terceros para manejar partes de la funcionalidad, como la autenticación o el correo electrónico de los usuarios.

Si bien el caso más común es uno en el que utilizas una API para conectarte a uno de los servicios en línea populares (Google, Twitter, etc.), hay ocasiones en que las dos aplicaciones que deseas conectar son las tuyas.

Esto me sucedió hace algún tiempo: había creado un carrito de compras personalizado como una aplicación de Ruby on Rails y, por un tiempo, me alegró usarlo junto con una página de destino HTML simple. Sin embargo, después de algún tiempo, encontré que para hacer que la página de destino fuera más atractiva, necesitaba actualizarla a algo que se actualizara con más frecuencia. Quería un blog, por lo que WordPress era la elección natural.

Con el sitio de WordPress construido, todo estaba bien, excepto por una pequeña cosa: cuando los visitantes agregaron artículos al carrito de compras y luego volvieron a comprar más, ¡se olvidaron de que habían agregado artículos a su carrito de compras! El carrito de compras y el sitio web necesitaban trabajar juntos. Necesitaba mostrar el contenido del carrito en el sitio web principal.

Este fue un lugar para algún desarrollo de API.

Al exponer la API del carrito de compras al mundo y luego llamarlo desde mi tema de WordPress, podría pasar los datos de una manera elegante, sin piratear ninguno de los sistemas.

En este tutorial, basado en las lecciones aprendidas al hacer este proyecto, analizaré ambos extremos de la comunicación de la API: Primero, con la ayuda de la gema Grape, crearemos una API para exponer una parte del carrito de compras basado en Ruby on Rails y lo enviaremos a aplicaciones externas. Luego, usaremos la API para recuperar el contenido del carrito de compras y mostrarlos en un sitio de WordPress. Dependiendo de cuáles sean tus necesidades, puedes descubrir que crear la API es lo que te interesa o que en realidad te interesa la parte sobre cómo llamar a una API externa desde WordPress. De cualquier manera, espero que encuentres el tutorial útil e interesante.

Para ejecutar el código en este tutorial, necesitarás la siguiente configuración:

  • Ruby on Rails versión 3.2
  • PHP 5.3
  • cURL y sus bibliotecas PHP / Apache

Si bien no hay nada realmente complicado en el tutorial, se requiere una comprensión básica de Ruby y Ruby on Rails, así como PHP y WordPress.

1. Conoce la aplicación de ejemplo

Como estás planeando conectar una aplicación Ruby on Rails a un sitio web impulsado por WordPress, probablemente sea seguro asumir que ya tienes una aplicación Rails (y tal vez incluso un sitio de WordPress) en funcionamiento. Por lo tanto, para las necesidades del tutorial, he creado una versión simplificada pero funcional del carrito de compras, con métodos para las acciones básicas que se requieren.

Puedes descargar el código de muestra o simplemente leer el tutorial y aplicarlo a tu propio proyecto Rails.

El ejemplo del proyecto Ruby on Rails es simple y consiste solo en un modelo (ShoppingCart) y un controlador (ShoppingCartController). En el modelo ShoppingCart, encontrarás los siguientes métodos:

  • find_or_create_with (token): este método estático busca y devuelve un objeto del carrito de compras con el token de identificación dado. Si no se encuentra uno (o no se otorga ningún token), se crea y devuelve un nuevo carrito de compra.
  • token: este método devuelve un token que identifica el objeto del carrito de compras actual.
  • as_json: Este método devuelve el contenido del carrito de compras como una cadena con formato JSON.

El controlador, ShoppingCartController contiene una acción para agregar artículos a un carrito. La acción, add, toma dos parámetros: token y (product) id:

http://<SERVER_PATH>/shopping_cart/add/<id>?token=<token>

Volveremos a todo esto más adelante, pero ahora, vamos a trabajar y creamos la API para el carrito de compras.

2. Instala Grape y crea una API

Ahora, con el proyecto Rails en su lugar, es hora de comenzar a crear la API.

Para construir nuestra API, usaremos una herramienta llamada Grape. Grape es un micro-framework diseñado para implementar API simples tipo REST en situaciones en las que, como dicen los desarrolladores, "no se necesita la capacidad de carga pesada de grandes frameworks como Rails".

El framework Grape se puede usar por sí solo, pero también se adapta bien a Rails, lo que proporciona una manera fácil de crear una API para acceder a un subconjunto (o por qué no a todos) de la funcionalidad de tu aplicación Rails. Que es exactamente lo que vamos a hacer en este tutorial.

Paso 1: Instalar Grape

Para agregar la gema a tu proyecto de Rails, agrega la siguiente línea a tu archivo Gemfile:

Luego actualiza tus gemas llamando (en la línea de comando):

Eso es. La gema ha sido instalada y podemos empezar a usarla.

Paso 2: Configurar las rutas de Grape 

Para comenzar a escribir la API, primero debes crear un archivo fuente Ruby que contendrá la funcionalidad de la API. Este es un framework ligero, por lo que podemos escribir la API completa en un solo archivo. Coloca este archivo dentro de tu aplicación Rails, en un directorio llamado api justo debajo del directorio principal app.

En el proyecto de ejemplo, encontrarás el código API en app/api/cart_external.rb.

Agrega las siguientes líneas a tu archivo de configuración application.rb para asegurarte de que los archivos en app/api estén incluidos:

Paso 3: Crea el módulo API

Dentro del archivo fuente de la API, ahora definiremos un módulo que contendrá nuestra clase API:

Esta es la versión más básica del contenido de una API de Grape simple. En este punto, todavía no hace nada, pero echemos un vistazo a los elementos de configuración al principio del código dentro de la clase.

  • Primero, la línea version 'v1', :using => :path indica que esta es la versión v1 de la API y que la versión a la que el usuario de la API desea acceder debe estar definida en la URL, por ejemplo, http://localhost:3000/v1/. Otras opciones para este campo de configuración son :header,:accept_version_header y :param, cada una de ellas define un método diferente para pasar la información de la versión. Consulta la documentación de Grape para obtener más información sobre el uso de cada uno de ellos.
  • format :json le dice a Grape que codifique las respuestas salientes como cadenas con formato JSON (también se pueden usar :txt y :xml).

Paso 4: Montar la API

Antes de comenzar a agregar funcionalidad a la API, como paso final de configuración, declara la clase API a tu aplicación Rails para que sepa cómo servirla a las personas y servicios que la soliciten.

Para hacer esto, agrega la siguiente línea a config/route.rb:

2. Hacer que la API haga algo

Ahora, volvamos a la clase CartExternal::API que definimos anteriormente.

Paso 1: Definir un recurso

Dentro de la clase API, encontrarás dos elementos que no mencioné todavía: helpers y resource.

  • helpers es una macro que se puede usar junto con un bloque (o un módulo) para introducir métodos helper que luego se pueden usar dentro de las acciones de la API. Estos métodos pueden ser, por ejemplo, los ayudantes necesarios para verificar los parámetros de la API o los métodos para comunicarse con la aplicación Rails principal.
  • resource define una colección lógica de métodos API. Puedes agregar tantos como desees, pero en nuestro caso lo haremos bien con solo uno, al que llamaremos :cart. Este recurso contendrá todos los métodos API relacionados con el carrito de compras. Con estas definiciones, todas las llamadas realizadas a http://<APPLICATION_PATH>/v1/cart se enrutarán a nuestro recurso y las acciones definidas dentro de él.

Paso 2: Crea tu primera acción API

Para ver cómo funciona esto, comencemos creando una llamada a la API para recuperar los artículos en un carrito de compras, identificado por el token de parámetro.

Dentro del bloque resources, agrega el siguiente código:

Ahora, hemos creado una acción que responde a las solicitudes GET enviadas a la ruta /items.

La acción toma un parámetro de cadena opcional, token, declarado en el bloque params. Si bien no es obligatorio declarar parámetros, es una buena práctica, ya que hace que tu código sea más legible y también te ahorra tiempo, ya que Grape hará la mayor parte de la validación de parámetros por ti. Para los parámetros requeridos, puedes usar una construcción similar, reemplazando opcionalmente con require. Los parámetros requeridos no pueden tener un valor predeterminado.

Nuestra acción busca un carrito de compras que coincida con el token o crea uno nuevo si no se pasa ningún token. Luego devuelve una respuesta codificada en JSON que consiste en un estado, el token real del carrito de compras y el contenido del mismo.

Paso 3: Prueba la acción API

Si estás ejecutando tu aplicación Rails localmente, ahora puedes iniciar el servidor e ingresar a http://localhost:3000/v1/cart/items para ver la respuesta, que debería tener este aspecto:

Como no pasamos un token en nuestra llamada, se creó un nuevo carrito de compras y se le asignó un valor de token único generado aleatoriamente. Es por eso también que el carrito está todavía vacío.

Si lo deseas, para realizar pruebas, puedes usar la acción add en ShoppingCartController para agregar un artículo al carrito:

http://localhost:3000/shopping_cart/add/1?token=TOKEN_FROM_PREVIOUS_CALL

Después de agregar el producto, cuando vuelvas a llamar a la API, notarás que ahora hay un artículo en el carrito:

{"status":200,"token":"XBrf2nCkTYfQJoU8d4A1nw","cart":{"item_count":1,"items":[{"cart_id":2,"created_at":"2014-05-20T16:44:24Z","id":4,"product_id":1,"product_name":"Test Product","product_price":"10.0","updated_at":"2014-05-20T16:44:24Z"}]}}

Agrega tantos elementos como desees, y luego, antes de agregar más funciones, completemos la configuración y hagamos que WordPress se comunique con la API.

3. Llama a la API desde WordPress

Ahora hemos probado la API llamándola desde un navegador web y, a continuación, es hora de hacer que WordPress se comunique con ella.

El código de WordPress que sigue se puede incluir en un complemento de WordPress o en functions.php de un tema de WordPress, dependiendo de tu proyecto y el contexto en el que se necesita la comunicación con la API. En mi propia integración de carrito de compras, decidí agregar el código en un tema hijo para simplificar.

De cualquier forma que decidas ir, el código será el mismo.

Paso 1: Crear una función para llamar a la API

Abre tu archivo functions.php (o un archivo PHP del plugin adecuado) e inserta la siguiente función PHP. Es una función auxiliar que encapsula la comunicación de la API, de modo que en el futuro, si necesitas cambiar la firma de la API u otros elementos genéricos en las llamadas, puedes hacerlo en un solo lugar.

Aquí están los huesos desnudos de lo que debe estar en esa función:

La función toma la ruta a la acción de la API y los parámetros requeridos, los combina en una URL y luego usa cURL para realizar una solicitud a la API.

Después de recibir la respuesta, la función la analiza en una matriz, utilizando json_decode, una función que forma parte de las bibliotecas estándar de PHP.

Paso 2: Comunicar la API y renderizar la respuesta

Ahora que hemos creado la funcionalidad para llamar a la API, usémosla para consultar el contenido del carrito de compras a través de nuestro método /cart/items de la API y luego vamos a mostrar la respuesta:

La función realiza una llamada a la API a /items e imprime la respuesta con algún formato HTML básico. Al final de la función, incluí un bloque print_r simple para representar el contenido de la respuesta JSON con fines de depuración.

Esto es útil especialmente al principio, cuando el carrito todavía está vacío y queremos asegurarnos de que no haya errores de comunicación que impidan que el código muestre su contenido.

Paso 3: Conectar la función a WordPress

Ahora que tenemos las funciones para realizar la llamada e imprimir la respuesta en su lugar, todo lo que queda es hacer que WordPress las llame.

La forma más sencilla de hacerlo sería ir directamente al tema y simplemente llamar a show_shopping_cart allí mismo, en el lugar donde deseas mostrar el carrito de compras. Si el tema es tuyo y estás seguro de que esto es todo lo que necesitas, podría ser una opción viable.

En el otro extremo del espectro se encuentra el enfoque más flexible y fácil de usar para incrustar la llamada en un widget de WordPress. De esta manera, puedes mover el carrito de compras y colocarlo en cualquier área de la barra lateral de tu sitio de WordPress. No es tan difícil, así que sigamos adelante y hagamos eso.

Todo lo que necesitamos es una subclase WP_Widget con un constructor y algún código para representar el contenido del carrito de compras en la función widget. Las otras dos funciones, form y options se pueden dejar vacías por ahora (si deseas agregar personalización al widget, aquí es donde irá).

Ahora, ve al administrador de WordPress y arrastra el widget del carrito de compras a una de tus barras laterales:

Ahora, visita el sitio de WordPress para ver el código en acción. Deberías ver algo como esto:

Tu carrito de compras todavía está vacío, pero como puedes ver en la salida de print_r debajo del carrito de compras, la comunicación funciona y el blog de WordPress está recibiendo datos de nuestra aplicación Rails.

Ahora, con lo básico cubierto, veamos cómo hacer que la comunicación sea un poco más segura.

4. Asegurar la conexión con una llave API

Ahora hemos creado una API para una aplicación de Ruby on Rails y la hemos llamado desde un sitio de WordPress. Sin embargo, aún falta algo importante: asegurar la API para que no esté abierta, y así todos los que se encuentren en Internet eviten llamarla a su gusto. Estoy seguro de que puedes pensar en todo tipo de cosas malas que sucederían si dejaras la puerta completamente abierta para todos, ¿verdad?

Una forma sencilla de proteger una API es generar una clave secreta para cada aplicación que permita llamar a su API. De esta manera, cada vez que una aplicación realice una solicitud a la API, debe enviar su clave API para que el servidor la verifique. Las personas que llaman sin una clave API válida no podrán realizar solicitudes. Para mayor seguridad, la mayoría de los servicios también incluyen un secreto de API además de la clave API.

Así que ahora, volvamos al trabajo y agreguemos la clave API, primero a nuestro código Ruby y luego en el lado de WordPress.

Paso 1: Agregar un método para verificar la clave API

Primero, agrega un método para verificar la clave API. Éste va en el bloque helpers de tu clase API:

Esta es una versión simple con una sola clave API, por lo que, dependiendo de tu aplicación, es posible que tengas que extenderla. Por ejemplo, si tienes varias aplicaciones que llaman a la API, deberás definir una clave API única para cada una de ellas y almacenarlas en la base de datos. También es posible que desees crear una página de administración para crear nuevas claves API.

Como mínimo, debes reemplazar API_KEY con una clave real generada que no sea demasiado fácil de adivinar. Sin embargo, para este ejemplo, todo lo que importa es que tienes una clave API y un método para verificar que la clave pasada coincida con la almacenada en el sistema.

Paso 2: Utilizar el método de ayuda para verificar una clave API

Con el método auxiliar en su lugar, podemos agregar la verificación de nuestra única llamada a la API rodeando el código que contiene con el siguiente constructor if...else:

Observa el bloque else donde generamos un error usando el método error! de Grape.

Ahora, reinicia el servidor Rails y vuelve a cargar tu página de inicio de WordPress y verás algo como esto:

Esto se debe a que aún no hemos agregado la clave API a nuestro código de WordPress y, por lo tanto, la API de Rails ya no acepta las solicitudes que realiza. Si lo deseas, en este punto, puedes agregar un manejo adecuado de errores y mostrar un mensaje de error agradable.

Entonces, continuemos y hagamos que la llamada a la API funcione de nuevo.

Paso 3: Agregar un campo de configuración para la clave API

Por ahora, puedes continuar y codificar la clave API en tu función api_get_as_json, pero como agregar nuevas opciones a la página de Configuración General de WordPress es muy sencillo, hagámoslo a través de un campo de configuración.

Y mientras lo agregamos, también podemos agregar una opción para definir la URL para la API.

De esta manera, más adelante, cuando implementes el código de WordPress en un servidor real en producción, podrás configurarlo sin tener que tocar el código, lo que siempre es bueno.

Aquí está la definición del campo de configuración para la URL del punto final de la API utilizando la misma construcción:

Visita el menú de configuración general de WordPress para establecer los valores adecuados para estas configuraciones, asegurándote de que la clave API coincida con lo que hayas establecido en tu servicio de Rails.

Paso 4: Pasar la clave de la API con las solicitudes de la API

Ahora, con la clave API y la URL almacenada en las opciones de WordPress, actualicemos la función que realiza la llamada a la API.

Los cambios van al principio de la función, así:

Al observar el nuevo código anterior, notarás que las configuraciones $api_key y $api_endpoint se leen desde las opciones de WordPress. $api_endpoint ya se usó para crear la URL para llamar, pero para $api_key, necesitamos agregar una línea (14) para incluir el valor en los parámetros enviados a la API.

Actualiza tu página de inicio de WordPress y el contenido del carrito de compras aparecerá nuevamente, esta vez asegurado con una clave API. Todo se ve bien, en realidad, lo mismo que antes de requerir la clave API, y has conectado la aplicación Rails con tu sitio de WordPress.

5. Agregar una sesión compartida

El código WordPress que hemos escrito hasta ahora hace llamadas a la API y las protege con una clave API, pero lo hace de una manera completamente sin estado. Para acciones simples y sin estado, como la publicación de actualizaciones en un tablero de mensajes o en tu propia plataforma de microblogging como Twitter, todo lo que necesitas son llamadas únicas como esta. Sin embargo, para nuestro ejemplo de carrito de compras, esto no es suficiente.

Como notarás cuando pruebes el código, mientras nuestro servidor Rails identifica un carrito de compras con un token, no lo hemos utilizado en ningún lugar, por lo que cada vez que se realiza una llamada a cart/list, el servidor crea un nuevo carrito de compras vacío. .

Esto no es bueno. Para que una conexión de carrito de compras sea de alguna utilidad, debes poder agregar artículos a tu carrito y mantenerlos allí durante un tiempo, incluso cuando pasas de una página a otra.

En una palabra, necesitas una sesión.

Hay varias formas de crear una sesión, pero vamos con la más simple, utilizando el token que nos ha sido entregado por la aplicación Rails y almacenándolo en una cookie del cliente. Como tu sitio de WordPress es la interfaz con la que el usuario (y tu navegador web) ve y se comunica, ahí también es donde debemos configurar la cookie.

Paso 1: Establecer una cookie

Las cookies solo se pueden configurar en el encabezado, antes de que se haya renderizado el contenido, por lo que necesitamos hacer un poco de reorganización en el código, moviendo /cart/items en el flujo de ejecución. Para hacer esto, vamos a crear una nueva función PHP, get_shopping_cart, y llamémosla al comienzo de la ejecución del sitio de WordPress.

Esto se puede hacer utilizando los hooks de acción de WordPress. Para obtener una lista completa de enlaces, puedes consultar el Codex de WordPress. En este caso, la acción init hace lo que necesitamos, así que conectemos nuestra solicitud a ese hook.

add_action( "init", "get_shopping_cart" );

La función get_shopping_cart se parece a esto:

Primero, la función realiza la llamada ya familiar a nuestra acción API de /items. Luego tenemos algo nuevo: en la línea 3, extraemos el token de carrito de compras devuelto por la API y luego, un par de líneas más tarde, lo guardamos en una cookie. La cookie está programada para caducar en 30 minutos, ya que supongo que alguien que esté comprando en una tienda en línea se habrá olvidado de la tienda en ese momento...

En la línea 7, puedes notar otra nueva llamada de función: set_saved_cart_data. Regresaremos a esto en un minuto. Pero primero, hagamos que las llamadas API usen el token también.

Paso 2: Utilizar el token de la cookie

Primero, vamos a crear una función auxiliar para recuperar el token de la cookie:

Y luego, usando esa función, agrega la siguiente línea a api_get_as_json, justo después de la línea donde establecemos el parámetro clave de API:

Con esta adición, cada vez que se realiza una llamada a la API, el método api_get_as_json busca el token del carrito de compras desde la cookie y lo agrega a los parámetros de solicitud. Si no se encuentra una cookie, la API recibirá un token vacío y tratará la llamada como un nuevo visitante, creando un nuevo carrito de compras vacío.

Paso 3: Optimizar la ejecución al guardar algunos datos

Y ahora, volvamos a set_saved_cart_data.

Como notamos en el código anterior, get_shopping_cart recibe el contenido completo del carrito de compras, los mismos datos que estamos consultando en show_shopping_cart. Esto significa que estamos llamando a la API dos veces en una página de WordPress cuando una llamada debería ser suficiente. Guardar la respuesta para la duración de la solicitud HTTP es una optimización simple que podemos usar para reducir la cantidad de llamadas API a la mitad.

En PHP, las variables globales son específicas y solo viven con una solicitud HTTP, por lo que podemos usar una para almacenar de forma segura los datos de get_shopping_cart hasta el punto donde se usa para representar el contenido del carrito de compras.

Para hacer esto, he creado un par de funciones simples, set_saved_cart_data y get_saved_cart_data, que envuelven la variable global $g_shopping_cart_data para mantener el código legible y fácil de mantener:

Con los datos del carrito de compras almacenados en una variable global, todo lo que necesitas hacer es cambiar la primera línea en show_shopping_cart a:

Con este cambio, el carrito de compras ahora tiene una sesión y el usuario puede agregar elementos al carrito y moverse entre las páginas mientras sigue viendo el mismo carrito de compras.

Paso 4: Hacer pruebas agregando algunos artículos al carrito

Para probar la funcionalidad, vamos a crear un enlace a la acción del controlador shopping_cart/add e imprimirlo al final de show_shopping_cart. Observa que para que el controlador comparta nuestra sesión también necesita el token del carrito de compras como parámetro:

Haz clic en el enlace Agregar elemento de prueba al carrito para agregar un elemento. Luego, vuelve a tu sitio de WordPress y ahora puedes ver un artículo del carrito de compras que aparece en el blog de WordPress.

Algunas palabras finales

Eso es todo: Ahora has conectado con éxito un carrito de compras basado en Ruby on Rails a tu blog o sitio web de WordPress.

Elimina la depuración de print_r, aplica estilo a la salida con algo de CSS y crea algunos enlaces reales como "Agregar al carrito" (también un botón "Retirar" que llevaría al usuario a la aplicación del carrito de compras real) y tendrás una integración del carrito de compras completamente funcional.

Sin embargo, lo más importante es que puedes utilizar el método de creación y respuesta a una API para vincular dos aplicaciones propias. Podrían ser cualquier cosa, así que ahora, ¡adelante y crea algunas APIs!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.