Febrero de 2009
Introducción
"¿Dónde está Ruby en la lista de bibliotecas cliente?"
Motivado por el ferviente apetito de nuestros desarrolladores y la perdurable popularidad de Ruby on Rails (RoR), mi colega Jeff Fisher ha creado una biblioteca de utilidades de Ruby a partir de las profundidades intrépidas de Mount Doom. Ten en cuenta que no es una biblioteca cliente completa, pero sí controla aspectos básicos como la autenticación y la manipulación básica de XML. También requiere que trabajes directamente con el feed de Atom mediante el módulo REXML y XPath.
Público
Este artículo está dirigido a desarrolladores interesados en acceder a las API de datos de Google a través de Ruby, específicamente en Ruby on Rails. Se supone que el lector está familiarizado con el lenguaje de programación Ruby y con el marco de trabajo de desarrollo web de Rails. Me enfoco en la API de lista de documentos para la mayoría de las muestras, pero los mismos conceptos se pueden aplicar a cualquiera de las API de datos.
Cómo comenzar
Requisitos
- Parche nivel 118.6 de Ruby 1.8.6 o superior descargar
- RubyGems 1.3.1 o superior descargar
- Rails 2.2.2+ descargar
Instala la biblioteca de utilidades de datos de Google para Ruby
Para obtener la biblioteca, puedes descargar la fuente de la biblioteca directamente desde el hosting del proyecto o instalar la gema:
sudo gem install gdata
Sugerencia: Por si acaso, ejecuta gem list --local
para verificar que la gema esté instalada correctamente.
Autenticación
ClientLogin
ClientLogin permite que tu aplicación acceda de manera programática a los usuarios a su cuenta de Google o G Suite. Después de validar las credenciales del usuario, Google emite un token de Auth al que se hace referencia en las solicitudes a la API posteriores. El token permanece válido por un período determinado, definido por el servicio de Google con el que estés trabajando. Por motivos de seguridad y para que los usuarios disfruten de una experiencia óptima, solo debes usar ClientLogin cuando desarrolles aplicaciones instaladas de escritorio. Para las aplicaciones web, se prefiere el uso de AuthSub o OAuth.
La biblioteca de Ruby tiene una clase de cliente para cada una de las API. Por ejemplo, usa el siguiente fragmento de código para acceder user@gmail.com
a la API de datos de listas de documentos:
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 de 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 cuando se producen intentos de acceso fallidos. Si eso sucede, puedes manejar 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 de Autenticación para aplicaciones instaladas a fin de obtener más información sobre cómo trabajar con CAPTCHA.
AuthSub
Genera 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 de cliente. Cada clase de servicio estableció un atributo authsub_scope
predeterminado, por lo que no es necesario especificar uno propio.
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
Actualiza 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 se le haya otorgado acceso a sus datos. Ten en cuenta que la URL es solo nuestra next_url
con el token de un solo uso agregado como un parámetro de consulta.
A continuación, intercambia el token de un solo uso por uno 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]
AuthSub seguro es muy similar. La única adición es configurar la 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 configurar secure=true
cuando solicites un token de un solo uso. Consulta Cómo generar la URL de AuthSubRequest más arriba.
Administración de tokens
AuthSub proporciona dos controladores adicionales, AuthSubTokenInfo y AuthSubRevocaToken para administrar los tokens. AuthSubTokenInfo
es útil para verificar la validez de un token. AuthSubRevokeToken
brinda a los usuarios la opción de descontinuar el acceso a sus datos. Como práctica recomendada, tu app debería usar AuthSubRevokeToken
. 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 de Autenticación de AuthSub para aplicaciones web para obtener la información más completa de AuthSub.
OAuth
Al momento de redactar este artículo, OAuth no se agregó al módulo GData::Auth
.
El uso de OAuth en la biblioteca de utilidades debería ser relativamente sencillo cuando se usa el oauth-plugin de Rails o oauth gem de Ruby. En cualquier caso, te recomendamos crear un objeto GData::HTTP::Request
y pasarle el encabezado Authorization
que genera cada biblioteca.
Cómo acceder a los feeds
GET (obtención de datos)
Una vez que hayas configurado un objeto de cliente, usa su método get()
para consultar un feed de datos de Google. XPath se puede usar para recuperar elementos Atom específicos. Aquí te mostramos un ejemplo de recuperación de 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á a 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 datos en el servidor, usa el método put()
de un cliente. En el siguiente ejemplo, se actualiza el título de un documento.
Se supone que tiene un feed de una consulta 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 <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 consulta 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)
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 andamiaje para crear tus archivos MVC.
Después de eso, se ejecuta rake db:migrate
para configurar las tablas de tu base de datos. Sin embargo, debido a que nuestra aplicación consultará los datos para la API de la Lista de documentos de Google, no necesitamos poca estructura básica o bases de datos. En su lugar, crea una aplicación nueva y un controlador simple:
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 desenchufa ActiveRecord
de la aplicación.
En la segunda línea, se carga la gema gdata
al inicio.
Por último, elegí 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'
Iniciar un control
Como no generamos una estructura, agrega de forma manual una acción llamada "all
" a DoclistController
en app/controllers/doclist_controller.rb
.
class DoclistController < ApplicationController def all @foo = 'I pity the foo!' end end
y crear all.html.erb
en app/views/doclist/
:
<%= @foo %>
Inicie el servidor web y comience el desarrollo
Ahora deberías poder iniciar el servidor web predeterminado si invocas ruby script/server
.
Si todo resulta bien, si tu navegador apunta a http://localhost:3000/
, debería mostrar "I pity the foo!
".
Sugerencia: No olvides quitar o cambiar el nombre de public/index.html
.
Una vez que todo esté funcionando, echa un vistazo a mi DoclistController
final y a ApplicationController
para conocer la carne del proyecto en DocList Manager. También querrás ver ContactsController
, que maneja 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, un segundo cercano es implementar tu aplicación. Por eso, recomiendo especialmente mod_rails para Apache. Es muy fácil de configurar, instalar y ejecutar. ¡Comenzarás enseguida!
Recursos
- Lista de las API de datos de Google
- Página del proyecto Biblioteca de utilidades de Ruby de Google Data
- Artículo: Cómo usar Ruby con las API de datos de Google
- Descargar Ruby
- Descargar RubyGems and Rails
Apéndice
Ejemplos
El Administrador de DocList es una muestra completa de Ruby on Rails que demuestra los temas que se analizan en este artículo. El código fuente completo está disponible en el hosting del proyecto.