Luty 2009 r.
Wprowadzenie
„Gdzie na liście bibliotek klienta jest Ruby?”
Zainspirowany ogromnym zainteresowaniem naszych programistów i nieustającą popularnością Ruby on Rails (RoR) mój kolega Jeff Fisher stworzył bibliotekę narzędzi Ruby z ognistych głębin Góry Przeznaczenia. Nie jest to pełna biblioteka klienta, ale obsługuje podstawowe funkcje, takie jak uwierzytelnianie i podstawowa manipulacja plikami XML. Wymaga to też bezpośredniej pracy z kanałem Atom za pomocą modułu REXML i XPath.
Odbiorcy
Ten artykuł jest przeznaczony dla deweloperów, którzy chcą uzyskać dostęp do interfejsów Google Data API za pomocą języka Ruby, a w szczególności Ruby on Rails. Zakładamy, że czytelnik ma pewną znajomość języka programowania Ruby i platformy Rails do tworzenia aplikacji internetowych. Większość przykładów dotyczy interfejsu Documents List API, ale te same koncepcje można zastosować do dowolnego interfejsu Data API.
Pierwsze kroki
Wymagania
- Ruby 1.8.6, poziom poprawki 114 lub nowszy pobierz
- RubyGems 1.3.1 lub nowsza pobierz
- Rails 2.2.2+ pobierz
Instalowanie biblioteki narzędzi Google Data Ruby
Aby uzyskać bibliotekę, możesz pobrać źródło biblioteki bezpośrednio z hostingu projektu lub zainstalować gem:
sudo gem install gdata
Wskazówka: dla pewności uruchom polecenie gem list --local
, aby sprawdzić, czy gem został prawidłowo zainstalowany.
Uwierzytelnianie
ClientLogin
ClientLogin umożliwia aplikacji programowe logowanie użytkowników na ich konta Google lub G Suite. Po zweryfikowaniu danych logowania użytkownika Google wydaje token uwierzytelniania, do którego można się odwoływać w kolejnych żądaniach interfejsu API. Token pozostaje ważny przez określony czas, który zależy od usługi Google, z której korzystasz. Ze względów bezpieczeństwa i aby zapewnić użytkownikom jak najlepsze wrażenia, interfejsu ClientLogin należy używać tylko podczas tworzenia zainstalowanych aplikacji na komputery. W przypadku aplikacji internetowych zalecamy używanie AuthSub lub OAuth.
Biblioteka Ruby zawiera klasę klienta dla każdego interfejsu API. Aby na przykład zalogować się w interfejsie Documents List Data API, użyj tego fragmentu kodu: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')
Zobacz pełną listę wdrożonych klas usług.
Jeśli usługa nie ma klasy klienta, użyj klasy GData::Client::Base
.
Na przykład poniższy kod wymusza logowanie się użytkowników za pomocą konta 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)
Uwaga: domyślnie biblioteka używa HOSTED_OR_GOOGLE
dla accountType
. Możliwe wartości to HOSTED_OR_GOOGLE
, HOSTED
lub GOOGLE
.
Jedną z wad korzystania z ClientLogin jest to, że w przypadku nieudanych prób logowania aplikacja może otrzymywać testy CAPTCHA. W takim przypadku możesz obsłużyć błąd, wywołując metodę clientlogin()
z dodatkowymi parametrami:client.clientlogin(username, password, captcha_token, captcha_answer)
. Więcej informacji o rozwiązywaniu testów CAPTCHA znajdziesz w pełnej dokumentacji Uwierzytelnianie w przypadku aplikacji zainstalowanych.
AuthSub
Generowanie adresu 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)
Poprzedni blok kodu tworzy w authsub_link
ten adres URL:
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
Możesz też użyć metody authsub_url
obiektu klienta. Każda klasa usług ma ustawiony domyślny atrybut authsub_scope
, więc nie musisz określać własnego.
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)
Poprzedni blok kodu tworzy ten adres 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
Przekształcanie tokena jednorazowego w token sesji
AuthSub przekieruje użytkownika z powrotem do http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN
, gdy przyzna on dostęp do swoich danych. Zwróć uwagę, że adres URL to po prostu nasz adres next_url
z dołączonym jednorazowym tokenem jako parametrem zapytania.
Następnie wymień token jednorazowy na token sesji o długim okresie ważności:
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]
Bezpieczna autoryzacja AuthSub działa bardzo podobnie. Jedyną zmianą jest ustawienie klucza prywatnego przed uaktualnieniem tokena:
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]
Uwaga: aby używać bezpiecznych tokenów, podczas wysyłania prośby o token jednorazowy ustaw wartość secure=true
. Zobacz Generowanie adresu URL AuthSubRequest powyżej.
Zarządzanie tokenami
AuthSub udostępnia 2 dodatkowe moduły obsługi: AuthSubTokenInfo i AuthSubRevokeToken, które służą do zarządzania tokenami. AuthSubTokenInfo
przydaje się do sprawdzania ważności tokena. AuthSubRevokeToken
daje użytkownikom możliwość przerwania dostępu do ich danych. Zgodnie ze sprawdzonymi metodami aplikacja powinna używać AuthSubRevokeToken
. Obie metody są obsługiwane w bibliotece Ruby.
Aby wysłać zapytanie dotyczące metadanych tokena:
client.auth_handler.info
Aby cofnąć token sesji:
client.auth_handler.revoke
Pełne informacje o AuthSub znajdziesz w dokumentacji Uwierzytelnianie AuthSub w aplikacjach internetowych.
OAuth
W momencie pisania tego artykułu autoryzacja OAuth nie została jeszcze dodana do modułu GData::Auth
.
Korzystanie z OAuth w bibliotece narzędziowej powinno być stosunkowo proste, jeśli używasz wtyczki oauth Rails lub gemu oauth Ruby. W obu przypadkach musisz utworzyć obiekt GData::HTTP::Request
i przekazać mu nagłówek Authorization
wygenerowany przez każdą bibliotekę.
Dostęp do plików danych
GET (pobieranie danych)
Po skonfigurowaniu obiektu klienta użyj jego metody get()
, aby wysłać zapytanie do pliku danych Google. Za pomocą XPath możesz pobierać konkretne elementy Atom. Oto przykład pobierania dokumentów Google użytkownika:
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 (tworzenie nowych danych)
Użyj metody post()
klienta, aby utworzyć nowe dane na serwerze. W tym przykładzie dodamy użytkownika
new_writer@example.com
jako współpracownika dokumentu o identyfikatorze 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 (aktualizacja danych)
Aby zaktualizować dane na serwerze, użyj metody put()
klienta. Poniższy przykład pokazuje, jak zaktualizować tytuł dokumentu.
Zakładamy, że masz plik danych z poprzedniego zapytania.
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)
USUŃ
Aby usunąć z serwera element <atom:entry> lub inne dane, użyj metody delete()
.
W tym przykładzie usuniemy dokument. Zakładamy, że masz wpis dokumentu
z poprzedniego zapytania.
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)
Tworzenie nowej aplikacji Rails
Zwykle pierwszym ćwiczeniem podczas tworzenia nowej aplikacji Rails jest uruchomienie generatorów szkieletów w celu utworzenia plików MVC.
Następnie uruchamia się rake db:migrate
, aby skonfigurować tabele bazy danych. Ponieważ jednak nasza aplikacja będzie wysyłać zapytania do interfejsu Google Documents List API w celu uzyskania danych, nie potrzebujemy ogólnych szkieletów ani baz danych. Zamiast tego utwórz nową aplikację i prosty kontroler:
rails doclist cd doclist ruby script/generate controller doclist
i wprowadź te zmiany w config/environment.rb
:
config.frameworks -= [ :active_record, :active_resource, :action_mailer ] config.gem 'gdata', :lib => 'gdata'
Pierwsza linia odłącza ActiveRecord
od aplikacji.
Drugi wiersz wczytuje klejnot gdata
podczas uruchamiania.
Na koniec połączyłem domyślną ścieżkę („/
”) z działaniem documents
w DoclistController
.
Dodaj ten wiersz do pliku config/routes.rb
:
map.root :controller => 'doclist', :action => 'all'
Uruchamianie kontrolera
Nie wygenerowaliśmy szkieletu, więc ręcznie dodaj działanie o nazwie „all
” do DoclistController
w app/controllers/doclist_controller.rb
.
class DoclistController < ApplicationController def all @foo = 'I pity the foo!' end end
i utwórz all.html.erb
w sekcji app/views/doclist/
:
<%= @foo %>
Uruchom serwer WWW i rozpocznij programowanie
Teraz możesz uruchomić domyślny serwer WWW, wywołując polecenie ruby script/server
.
Jeśli wszystko jest w porządku, po otwarciu w przeglądarce adresu http://localhost:3000/
powinien wyświetlić się tekst „I pity the foo!
”.
Wskazówka: nie zapomnij usunąć lub zmienić nazwy public/index.html
.
Gdy wszystko będzie działać, zapoznaj się z moimi ostatecznymi wersjami DoclistController
i ApplicationController
, aby poznać najważniejsze elementy projektu DocList Manager. Warto też przyjrzeć się plikowi ContactsController
, który obsługuje wywołania interfejsu Google Contacts API.
Podsumowanie
Najtrudniejszą częścią tworzenia aplikacji Google Data Rails jest skonfigurowanie Rails. Drugim najważniejszym krokiem jest wdrożenie aplikacji. W tym celu zdecydowanie polecam mod_rails dla Apache. Jest bardzo łatwy w konfiguracji, instalacji i uruchomieniu. Zaczniesz korzystać z usługi w mgnieniu oka.
Zasoby
- Lista interfejsów Google Data API
- Strona projektu Google Data Ruby Utility Library
- Artykuł: Korzystanie z języka Ruby w interfejsach Google Data API
- Pobierz Ruby
- Pobieranie RubyGems i Rails
Dodatek
Przykłady
DocList Manager to pełny przykład w Ruby on Rails, który ilustruje tematy omówione w tym artykule. Pełny kod źródłowy jest dostępny w hostingu projektu.