Febrero de 2009
Introducción
"¿Dónde está Ruby en la lista de bibliotecas cliente?"
Motivado por el apetito voraz de nuestros desarrolladores y la popularidad duradera de Ruby on Rails (RoR), mi colega Jeff Fisher forjó una biblioteca de utilidades de Ruby desde las profundidades ardientes del Monte Doom. Ten en cuenta que no es una biblioteca cliente completa, pero sí controla los aspectos básicos, como la autenticación y la manipulación básica de XML. También requiere que trabajes directamente con el feed Atom usando el módulo REXML y XPath.
Público
Este artículo está dirigido a los desarrolladores interesados en acceder a las APIs de Google Data con Ruby, específicamente Ruby on Rails. Se supone que el lector tiene cierta familiaridad con el lenguaje de programación Ruby y el marco de trabajo de desarrollo web de Rails. Me enfoco en la API de Documents List para la mayoría de los ejemplos, pero los mismos conceptos se pueden aplicar a cualquiera de las APIs de Data.
Comenzar
Requisitos
- Ruby 1.8.6, nivel de parche 114 o posterior descargar
- RubyGems 1.3.1 o versiones posteriores descargar
- Descarga Rails 2.2.2 o versiones posteriores.
Instala la biblioteca de utilidades de Google Data para Ruby
Para obtener la biblioteca, puedes descargar la fuente de la biblioteca directamente desde el alojamiento del proyecto o instalar la gem:
sudo gem install gdata
Sugerencia: Para mayor seguridad, ejecuta gem list --local
para verificar que la gem se haya instalado correctamente.
Autenticación
ClientLogin
ClientLogin permite que tu aplicación acceda de forma programática a las cuentas de Google o de G Suite de los usuarios. Después de validar las credenciales del usuario, Google emite un token de autorización para que se haga referencia a él en las solicitudes posteriores a la API. El token sigue siendo válido durante un período determinado, que define el servicio de Google con el que trabajas. Por motivos de seguridad y para brindarles a los usuarios la mejor experiencia, solo debes usar ClientLogin cuando desarrolles aplicaciones instaladas para computadoras. Para las aplicaciones web, se recomienda usar AuthSub o OAuth.
La biblioteca de Ruby tiene una clase de cliente para cada una de las APIs. Por ejemplo, usa el siguiente fragmento de código para acceder a user@gmail.com
en la API de Documents List Data:
client = GData::Client::DocList.new client.clientlogin('user@gmail.com', 'pa$$word')
The YouTube Data API would be:
client = GData::Client::YouTube.new client.clientlogin('user@gmail.com', 'pa$$word')
Consulta la lista completa de clases de servicio implementadas.
Si un servicio no tiene una clase cliente, usa la clase GData::Client::Base
.
Por ejemplo, el siguiente código obliga a los usuarios a acceder con una cuenta de G Suite.
client_login_handler = GData::Auth::ClientLogin
.new('writely', :account_type => 'HOSTED')
token = client_login_handler.get_token('user@example.com', 'pa$$word', 'google-RailsArticleSample-v1')
client = GData::Client::Base.new(:auth_handler => client_login_handler)
Nota: De forma predeterminada, la biblioteca usa HOSTED_OR_GOOGLE
para el accountType
. Los valores posibles son HOSTED_OR_GOOGLE
, HOSTED
o GOOGLE
.
Una de las desventajas de usar ClientLogin es que tu aplicación puede recibir desafíos de CAPTCHA en los intentos de acceso fallidos. Si eso sucede, puedes controlar el error llamando al método clientlogin()
con sus parámetros adicionales: client.clientlogin(username, password, captcha_token, captcha_answer)
. Consulta la documentación completa sobre la autenticación para aplicaciones instaladas para obtener más información sobre cómo controlar los CAPTCHA.
AuthSub
Cómo generar la URL de AuthSubRequest
scope = 'http://www.google.com/calendar/feeds/' next_url = 'http://example.com/change/to/your/app' secure = false # set secure = true for signed AuthSub requests sess = true authsub_link = GData::Auth::AuthSub.get_url(next_url, scope, secure, sess)
El bloque de código anterior crea la siguiente URL en authsub_link
:
https://www.google.com/accounts/AuthSubRequest?next=http%3A%2F%2Fexample.com%2Fchange%2Fto%2Fyour%2Fapp&scope=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F&session=1&secure=0
También puedes usar el método authsub_url
del objeto cliente. Cada clase de servicio tiene establecido un atributo authsub_scope
predeterminado, por lo que no es necesario que especifiques el tuyo.
client = GData::Client::DocList.new next_url = 'http://example.com/change/to/your/app' secure = false # set secure = true for signed AuthSub requests sess = true domain = 'example.com' # force users to login to a G Suite hosted domain authsub_link = client.authsub_url(next_url, secure, sess, domain)
El bloque de código anterior crea la siguiente URL:
https://www.google.com/accounts/AuthSubRequest?next=http%3A%2F%2Fexample.com%2Fchange%2Fto%2Fyour%2Fapp&scope=http%3A%2F%2Fdocs.google.com%2Ffeeds%2F&session=1&secure=0&hd=example.com
Cómo actualizar un token de un solo uso a un token de sesión
AuthSub redireccionará al usuario a http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN
una vez que haya otorgado acceso a sus datos. Ten en cuenta que la URL es solo nuestro next_url
con el token de un solo uso agregado como parámetro de consulta.
A continuación, intercambia el token de un solo uso por un token de sesión de larga duración:
client.authsub_token = params[:token] # extract the single-use token from the URL query params session[:token] = client.auth_handler.upgrade() client.authsub_token = session[:token] if session[:token]
Secure AuthSub es muy similar. La única adición es configurar tu clave privada antes de actualizar el token:
PRIVATE_KEY = '/path/to/private_key.pem' client.authsub_token = params[:token] client.authsub_private_key = PRIVATE_KEY session[:token] = client.auth_handler.upgrade() client.authsub_token = session[:token] if session[:token]
Nota: Para usar tokens seguros, asegúrate de establecer secure=true
cuando solicites un token de un solo uso. Consulta Cómo generar la URL de AuthSubRequest, que se encuentra más arriba.
Administración de tokens
AuthSub proporciona dos controladores adicionales, AuthSubTokenInfo y AuthSubRevokeToken, para administrar tokens. AuthSubTokenInfo
es útil para verificar la validez de un token. AuthSubRevokeToken
les brinda a los usuarios la opción de interrumpir el acceso a sus datos. Tu app debe usar AuthSubRevokeToken
como práctica recomendada. Ambos métodos son compatibles con la biblioteca de Ruby.
Para consultar los metadatos de un token, haz lo siguiente:
client.auth_handler.info
Para revocar un token de sesión, haz lo siguiente:
client.auth_handler.revoke
Consulta la documentación completa sobre la autenticación de AuthSub para aplicaciones web para obtener todos los detalles sobre AuthSub.
OAuth
Al momento de escribir este artículo, OAuth no se había agregado al módulo GData::Auth
.
Usar OAuth en la biblioteca de utilidades debería ser relativamente sencillo cuando se usa el oauth-plugin de Rails o la gema oauth de Ruby. En cualquier caso, querrás crear un objeto GData::HTTP::Request
y pasarle el encabezado Authorization
que genera cada biblioteca.
Cómo acceder a los feeds
GET (recuperación de datos)
Una vez que hayas configurado un objeto cliente, usa su método get()
para consultar un feed de datos de Google. XPath se puede usar para recuperar elementos Atom específicos. A continuación, se muestra un ejemplo de cómo recuperar los documentos de Google de un usuario:
feed = client.get('http://docs.google.com/feeds/documents/private/full').to_xml feed.elements.each('entry') do |entry| puts 'title: ' + entry.elements['title'].text puts 'type: ' + entry.elements['category'].attribute('label').value puts 'updated: ' + entry.elements['updated'].text puts 'id: ' + entry.elements['id'].text # Extract the href value from each <atom:link> links = {} entry.elements.each('link') do |link| links[link.attribute('rel').value] = link.attribute('href').value end puts links.to_s end
POST (creación de datos nuevos)
Usa el método post()
de un cliente para crear datos nuevos en el servidor. En el siguiente ejemplo, se agregará new_writer@example.com
como colaborador al documento con el ID doc_id
.
# Return documents the authenticated user owns feed = client.get('http://docs.google.com/feeds/documents/private/full/-/mine').to_xml entry = feed.elements['entry'] # first <atom:entry> acl_entry = <<-EOF <entry xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'> <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/> <gAcl:role value='writer'/> <gAcl:scope type='user' value='new_writer@example.com'/> </entry> EOF # Regex the document id out from the full <atom:id>. # http://docs.google.com/feeds/documents/private/full/document%3Adfrk14g25fdsdwf -> document%3Adfrk14g25fdsdwf doc_id = entry.elements['id'].text[/full\/(.*%3[aA].*)$/, 1] response = client.post("http://docs.google.com/feeds/acl/private/full/#{doc_id}", acl_entry)
PUT (actualización de datos)
Para actualizar los datos en el servidor, usa el método put()
de un cliente. En el siguiente ejemplo, se actualizará el título de un documento.
Se supone que tienes un feed de una búsqueda anterior.
entry = feed.elements['entry'] # first <atom:entry> # Update the document's title entry.elements['title'].text = 'Updated title' entry.add_namespace('http://www.w3.org/2005/Atom') entry.add_namespace('gd','http://schemas.google.com/g/2005') edit_uri = entry.elements["link[@rel='edit']"].attributes['href'] response = client.put(edit_uri, entry.to_s)
BORRAR
Para borrar un elemento <atom:entry> o cualquier otro dato del servidor, usa el método delete()
.
En el siguiente ejemplo, se borrará un documento. El código supone que tienes una entrada de documento de una búsqueda anterior.
entry = feed.elements['entry'] # first <atom:entry> edit_uri = entry.elements["link[@rel='edit']"].attributes['href'] client.headers['If-Match'] = entry.attribute('etag').value # make sure we don't nuke another client's updates client.delete(edit_uri)
Cómo crear una nueva aplicación de Rails
Por lo general, el primer ejercicio para crear una app de Rails nueva implica ejecutar los generadores de scaffold para crear tus archivos de MVC.
Después de eso, se ejecuta rake db:migrate
para configurar las tablas de la base de datos. Sin embargo, dado que nuestra aplicación consultará la API de Google Documents List para obtener datos, no necesitamos mucho scaffolding genérico ni bases de datos. En su lugar, crea una aplicación y un controlador simples nuevos:
rails doclist cd doclist ruby script/generate controller doclist
y realiza los siguientes cambios en config/environment.rb
:
config.frameworks -= [ :active_record, :active_resource, :action_mailer ] config.gem 'gdata', :lib => 'gdata'
La primera línea desvincula ActiveRecord
de la aplicación.
La segunda línea carga la gema gdata
durante el inicio.
Por último, decidí conectar la ruta predeterminada ("/
") a la acción documents
en DoclistController
.
Agrega esta línea a config/routes.rb
:
map.root :controller => 'doclist', :action => 'all'
Cómo iniciar un controlador
Como no generamos código de ejemplo, agrega manualmente una acción llamada "all
" al DoclistController
en app/controllers/doclist_controller.rb
.
class DoclistController < ApplicationController def all @foo = 'I pity the foo!' end end
y crea all.html.erb
en app/views/doclist/
:
<%= @foo %>
Inicia el servidor web y comienza el desarrollo
Ahora deberías poder iniciar el servidor web predeterminado invocando ruby script/server
.
Si todo está bien, al dirigir el navegador a http://localhost:3000/
, debería mostrarse "I pity the foo!
".
Nota: No olvides quitar o cambiar el nombre de public/index.html
.
Una vez que todo funcione, consulta mi DoclistController
y ApplicationController
finales para conocer el contenido principal del proyecto DocList Manager. También te recomendamos que consultes ContactsController
, que controla las llamadas a la API de Contactos de Google.
Conclusión
La parte más difícil de crear una app de Google Data Rails es configurar Rails. Sin embargo, la segunda tarea más importante es implementar tu aplicación. Para ello, te recomiendo mod_rails para Apache. Es muy fácil de configurar, instalar y ejecutar. ¡Estarás listo para comenzar en muy poco tiempo!
Recursos
- Lista de APIs de datos de Google
- Página del proyecto de la biblioteca de utilidades de Ruby para datos de Google
- Artículo: Cómo usar Ruby con las APIs de Google Data
- Descarga Ruby
- Descarga RubyGems y Rails
Apéndice
Ejemplos
El Administrador de DocList es una muestra completa de Ruby on Rails que demuestra los temas analizados en este artículo. El código fuente completo está disponible en el alojamiento del proyecto.