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.