Février 2009
Introduction
"Où se trouve Ruby dans la liste des bibliothèques clientes ?"
Motivé par l'appétit vorace de nos développeurs et la popularité durable de Ruby on Rails (RoR), mon collègue Jeff Fisher a forgé une bibliothèque d'utilitaires Ruby dans les profondeurs ardentes du Mont Doom. Notez qu'il ne s'agit pas d'une bibliothèque cliente complète, mais qu'elle gère les principes de base tels que l'authentification et la manipulation XML de base. Vous devez également travailler directement avec le flux Atom à l'aide du module REXML et de XPath.
Audience
Cet article s'adresse aux développeurs qui souhaitent accéder aux API Google Data à l'aide de Ruby, et plus particulièrement de Ruby on Rails. Il part du principe que le lecteur connaît déjà le langage de programmation Ruby et le framework de développement Web Rails. Je me concentre sur l'API Documents List pour la plupart des exemples, mais les mêmes concepts peuvent être appliqués à n'importe quelle API Data.
Premiers pas
Conditions requises
- Ruby 1.8.6, niveau de correctif 114 ou version ultérieure télécharger
- RubyGems 1.3.1 ou version ultérieure téléchargement
- Rails 2.2.2+ téléchargement
Installer la bibliothèque d'utilitaires Ruby Google Data
Pour obtenir la bibliothèque, vous pouvez télécharger la source de la bibliothèque directement à partir de l'hébergement du projet ou installer le gem :
sudo gem install gdata
Conseil : Pour plus de sécurité, exécutez gem list --local
pour vérifier que le gem a été installé correctement.
Authentification
ClientLogin
ClientLogin permet à votre application de connecter les utilisateurs à leur compte Google ou G Suite de manière programmatique. Après avoir validé les identifiants de l'utilisateur, Google émet un jeton d'authentification à référencer dans les requêtes d'API ultérieures. Le jeton reste valide pendant une durée définie par le service Google que vous utilisez. Pour des raisons de sécurité et pour offrir la meilleure expérience à vos utilisateurs, vous ne devez utiliser ClientLogin que lorsque vous développez des applications de bureau installées. Pour les applications Web, il est préférable d'utiliser AuthSub ou OAuth.
La bibliothèque Ruby comporte une classe cliente pour chacune des API. Par exemple, utilisez l'extrait de code suivant pour vous connecter à l'API Documents List Data :user@gmail.com
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')
Consultez la liste complète des classes de service implémentées.
Si un service ne dispose pas de classe cliente, utilisez la classe GData::Client::Base
.
Par exemple, le code suivant oblige les utilisateurs à se connecter avec un compte 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)
Remarque : Par défaut, la bibliothèque utilise HOSTED_OR_GOOGLE
pour accountType
. Les valeurs possibles sont HOSTED_OR_GOOGLE
, HOSTED
ou GOOGLE
.
L'un des inconvénients de l'utilisation de ClientLogin est que votre application peut recevoir des tests CAPTCHA en cas d'échec de tentatives de connexion. Dans ce cas, vous pouvez gérer l'erreur en appelant la méthode clientlogin()
avec ses paramètres supplémentaires : client.clientlogin(username, password, captcha_token, captcha_answer)
. Pour en savoir plus sur la gestion des CAPTCHA, consultez la documentation complète sur l'authentification pour les applications installées.
AuthSub
Générer l'URL 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)
Le bloc de code précédent crée l'URL suivante dans 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
Vous pouvez également utiliser la méthode authsub_url
de l'objet client. Chaque classe de service a défini un attribut authsub_scope
par défaut. Vous n'avez donc pas besoin de spécifier le vôtre.
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)
Le bloc de code précédent crée l'URL suivante :
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
Mettre à niveau un jeton à usage unique en jeton de session
AuthSub redirige l'utilisateur vers http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN
une fois qu'il a accordé l'accès à ses données. Notez que l'URL n'est que notre next_url
avec le jeton à usage unique ajouté en tant que paramètre de requête.
Ensuite, échangez le jeton à usage unique contre un jeton de session à longue durée de vie :
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 est très semblable. La seule chose à ajouter est de définir votre clé privée avant de mettre à niveau le jeton :
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]
Remarque : Pour utiliser des jetons sécurisés, veillez à définir secure=true
lorsque vous demandez un jeton à usage unique. Consultez la section Générer l'URL AuthSubRequest ci-dessus.
Gestion des jetons
AuthSub fournit deux gestionnaires supplémentaires, AuthSubTokenInfo et AuthSubRevokeToken, pour gérer les jetons. AuthSubTokenInfo
est utile pour vérifier la validité d'un jeton. AuthSubRevokeToken
permet aux utilisateurs de mettre fin à l'accès à leurs données. Votre application doit utiliser AuthSubRevokeToken
comme bonne pratique. Les deux méthodes sont compatibles avec la bibliothèque Ruby.
Pour interroger les métadonnées d'un jeton :
client.auth_handler.info
Pour révoquer un jeton de session :
client.auth_handler.revoke
Pour en savoir plus sur AuthSub, consultez la documentation complète sur l'authentification AuthSub pour les applications Web.
OAuth
Au moment de la rédaction de cet article, OAuth n'a pas été ajouté au module GData::Auth
.
L'utilisation d'OAuth dans la bibliothèque utilitaire devrait être relativement simple avec le plug-in OAuth Rails ou la gem OAuth Ruby. Dans les deux cas, vous devez créer un objet GData::HTTP::Request
et lui transmettre l'en-tête Authorization
généré par chaque bibliothèque.
Accéder aux flux
GET (récupération de données)
Une fois que vous avez configuré un objet client, utilisez sa méthode get()
pour interroger un flux de données Google. XPath peut être utilisé pour récupérer des éléments Atom spécifiques. Voici un exemple de récupération des documents Google d'un utilisateur :
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 (création de données)
Utilisez la méthode post()
d'un client pour créer des données sur le serveur. L'exemple suivant ajoute new_writer@example.com
en tant que collaborateur au document dont l'ID est 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 (mise à jour des données)
Pour mettre à jour les données sur le serveur, utilisez la méthode put()
d'un client. L'exemple suivant met à jour le titre d'un document.
Il suppose que vous disposez d'un flux provenant d'une requête précédente.
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)
SUPPRIMER
Pour supprimer une entrée <atom:entry> ou d'autres données du serveur, utilisez la méthode delete()
.
L'exemple suivant supprime un document. Le code suppose que vous disposez d'une entrée de document provenant d'une requête précédente.
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)
Créer une application Rails
En général, le premier exercice de création d'une application Rails consiste à exécuter les générateurs de scaffold pour créer vos fichiers MVC.
Ensuite, il exécute rake db:migrate
pour configurer vos tables de base de données. Toutefois, comme notre application interrogera l'API Google Documents List pour obtenir des données, nous n'avons pas vraiment besoin d'échafaudages ni de bases de données génériques. Créez plutôt une application et un contrôleur simples :
rails doclist cd doclist ruby script/generate controller doclist
et apportez les modifications suivantes à config/environment.rb
:
config.frameworks -= [ :active_record, :active_resource, :action_mailer ] config.gem 'gdata', :lib => 'gdata'
La première ligne détache ActiveRecord
de l'application.
La deuxième ligne charge le gem gdata
au démarrage.
Enfin, j'ai choisi de connecter la route par défaut (/
) à l'action documents
dans DoclistController
.
Ajoutez la ligne suivante à config/routes.rb
:
map.root :controller => 'doclist', :action => 'all'
Démarrer un contrôleur
Comme nous n'avons pas généré de scaffolding, ajoutez manuellement une action appelée "all
" à DoclistController
dans app/controllers/doclist_controller.rb
.
class DoclistController < ApplicationController def all @foo = 'I pity the foo!' end end
et créez all.html.erb
sous app/views/doclist/
:
<%= @foo %>
Lancer le serveur Web et commencer le développement
Vous devriez maintenant pouvoir démarrer le serveur Web par défaut en appelant ruby script/server
.
Si tout se passe bien, l'adresse http://localhost:3000/
devrait afficher I pity the foo!
.
Conseil : N'oubliez pas de supprimer ou de renommer public/index.html
.
Une fois que tout fonctionne, jetez un coup d'œil à mes DoclistController
et ApplicationController
finaux pour le cœur du projet DocList Manager. Vous devez également examiner ContactsController
, qui gère les appels à l'API Google Contacts.
Conclusion
La partie la plus difficile de la création d'une application Rails Google Data consiste à configurer Rails. Toutefois, le déploiement de votre application arrive en deuxième position. Pour cela, je vous recommande vivement mod_rails pour Apache. Il est très facile à configurer, à installer et à exécuter. Vous serez opérationnel en un rien de temps !
Ressources
- Liste des API Google Data
- Page du projet Google Data Ruby Utility Library
- Article : Utiliser Ruby avec les API Google Data
- Télécharger Ruby
- Télécharger RubyGems et Rails
Annexe
Exemples
Le gestionnaire DocList est un exemple complet de Ruby on Rails qui illustre les sujets abordés dans cet article. Le code source complet est disponible sur l'hébergement du projet.