Luty 2009 r.
Wprowadzenie
„Gdzie jest Ruby na liście bibliotek klienta?”
Zachęcony gwałtownym apetytem naszych programistów i wieloletnią popularnością Ruby on Rails (RoR) mój kolega, Jeff Fisher, sfałszował bibliotekę Ruby z ogromnej głębokości góry Doom. Nie jest to kompleksowa biblioteka klienta, ale obsługuje takie podstawowe elementy, jak uwierzytelnianie czy podstawowa manipulacja XML. Wymaga też bezpośredniej pracy z kanałem Atom za pomocą modułu REXML i ścieżki XPath.
Odbiorcy
Ten artykuł jest przeznaczony dla deweloperów zainteresowanych korzystaniem z interfejsów API danych Google przy użyciu systemu Ruby, w szczególności Ruby on Rails. Zakładamy, że czytelnik ma wiedzę na temat języka programowania Ruby i platformy programowania stron internetowych The Rails. Postaram się skupić na interfejsie Documents List API dla większości przykładów, ale te same koncepcje można zastosować do dowolnych interfejsów Data API.
Pierwsze kroki
Wymagania
- Poprawka do pakietu Ruby 1.8.6 (poziom 114+) do pobrania
- RubyGems 1.3.1+ do pobrania
- Rails 2.2.2+ do pobrania
Instalowanie biblioteki narzędzi Google Data Ruby
Aby uzyskać bibliotekę, możesz pobrać źródło biblioteki bezpośrednio z projektu na serwerze lub zainstalować klejnot:
sudo gem install gdata
Wskazówka: aby mieć pewność, że klejnot został prawidłowo zainstalowany, uruchom gem list --local
.
Uwierzytelnianie
ClientLogin
ClientLogin pozwala aplikacji na automatyczne logowanie użytkowników na konta Google lub G Suite. Po zweryfikowaniu danych logowania użytkownika Google wysyła token uwierzytelniania, który może zostać użyty w kolejnych żądaniach do interfejsu API. Token pozostaje ważny przez określony czas zdefiniowany w dowolnej usłudze Google, z którą współpracujesz. Ze względów bezpieczeństwa i dla wygody użytkowników używaj tylko ClientLogin podczas tworzenia zainstalowanych aplikacji komputerowych. W przypadku aplikacji internetowych zalecamy korzystanie z AuthSub lub OAuth.
Biblioteka Ruby zawiera klasę klienta dla każdego z interfejsów API. Na przykład możesz użyć tego fragmentu kodu, aby zalogować się do user@gmail.com
za pomocą interfejsu Documents List Data API:
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ługi.
Jeśli usługa nie ma klasy klienta, użyj klasy GData::Client::Base
.
Na przykład ten kod wymusza na użytkownikach logowanie się 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 accountType
używa biblioteki HOSTED_OR_GOOGLE
. Możliwe wartości to HOSTED_OR_GOOGLE
, HOSTED
lub GOOGLE
.
Jedną z wad każdego z nich jest to, że w przypadku nieudanych prób logowania aplikacja może wysyłać testy CAPTCHA. W takim przypadku możesz usunąć błąd, wywołując metodę clientlogin()
z dodatkowymi parametrami: client.clientlogin(username, password, captcha_token, captcha_answer)
. Więcej informacji o korzystaniu z CAPTCHA znajdziesz w pełnej dokumentacji uwierzytelniania dla zainstalowanych aplikacji.
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ługi ma ustawiony domyślny atrybut authsub_scope
, więc nie trzeba określać własnej.
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
Uaktualnienie tokena jednorazowego do tokena sesji
AuthSub przekieruje użytkownika z powrotem do http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN
po przyznaniu mu dostępu do danych. Zwróć uwagę, że adres URL to po prostu next_url
z tokenem jednorazowym dołączonym jako parametr zapytania.
Następnie wymień token jednorazowy na token długoterminowej sesji:
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]
Zabezpieczenie AuthSub jest bardzo podobne. Jedynym dodatkiem 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: jeśli chcesz używać tokenów bezpiecznych, ustaw żądanie jednorazowego tokena jako secure=true
. Przeczytaj sekcję Generowanie adresu URL AuthSubRequest powyżej.
Zarządzanie tokenami
AuthSub udostępnia 2 dodatkowe moduły obsługi: AuthSubTokenInfo i AuthSubRevokeToken do zarządzania tokenami. AuthSubTokenInfo
przydaje się do sprawdzania poprawności tokena. AuthSubRevokeToken
umożliwia użytkownikom odłączenie dostępu do ich danych. Sprawdzoną metodą jest używanie AuthSubRevokeToken
. Obie metody są obsługiwane w bibliotece Ruby.
Aby wysłać zapytanie do metadanych tokena:
client.auth_handler.info
Aby unieważnić token sesji:
client.auth_handler.revoke
Pełne informacje o AuthSub znajdziesz w pełnej dokumentacji uwierzytelniania AuthSub dla aplikacji internetowych.
OAuth
W momencie tworzenia tego artykułu do protokołu GData::Auth
nie dodano protokołu OAuth.
Korzystanie z protokołu OAuth w bibliotece narzędzi powinno być stosunkowo proste podczas korzystania z wtyczki oauth-plugin lub ruby oauth gem. W obu przypadkach musisz utworzyć obiekt GData::HTTP::Request
i przekazać do niego nagłówek Authorization
wygenerowany przez każdą bibliotekę.
Dostęp do kanałów
GET (pobieranie danych)
Po skonfigurowaniu obiektu klienta użyj jego metody get()
, aby utworzyć zapytanie dotyczące pliku danych Google. XPath może służyć do pobierania określonych elementów Atom. Oto przykład pobrania 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. Ten przykład dodaje użytkownika new_writer@example.com
jako współpracownika do 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 (aktualizowanie danych)
Aby zaktualizować dane na serwerze, użyj metody put()
klienta. Poniższy przykład spowoduje zaktualizowanie tytułu dokumentu.
Przy założeniu, ż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ąć tag <atom:entry> lub inne dane z serwera, użyj metody delete()
.
Poniższy przykład spowoduje usunięcie dokumentu. Kod zakłada, że masz dokument 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
Pierwszym ćwiczeniem w celu utworzenia nowej aplikacji Rails jest utworzenie generatorów rusztowań w celu utworzenia plików MVC.
Po tym czasie aplikacja korzysta z rake db:migrate
, aby konfigurować tabele bazy danych. Ponieważ jednak nasza aplikacja będzie wysyłać zapytania do interfejsu Google Documents List API, aby znaleźć dane, nie musimy już używać szkieletów lub 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 pliku config/environment.rb
:
config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
config.gem 'gdata', :lib => 'gdata'
Pierwszy wiersz odłącza wartość ActiveRecord
z aplikacji.
Drugi wiersz wczytuje klejnot gdata
przy uruchomieniu.
Na koniec zdecydowałem się połączyć trasę domyślną („/
”) z działaniem documents
w DoclistController
.
Dodaj ten wiersz do config/routes.rb
:
map.root :controller => 'doclist', :action => 'all'
Uruchom kontroler
Nie generowaliśmy rusztowania, 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 app/views/doclist/
:
<%= @foo %>
Uruchom serwer WWW i zacznij programować
Teraz możesz uruchomić domyślny serwer WWW przez wywoływanie ruby script/server
.
Jeśli wszystko jest w porządku, ustaw w przeglądarce adres http://localhost:3000/
na „I pity the foo!
”.
Wskazówka: nie zapomnij usunąć nazwy public/index.html
lub zmienić jej nazwy.
Gdy wszystko będzie gotowe, zobacz moje ostateczne wersje: DoclistController
i ApplicationController
w projekcie dla menedżera projektu DocList. Możesz też użyć narzędzia ContactsController
, które obsługuje wywołania interfejsu Google Contacts API.
Podsumowanie
Najtrudniejszym etapem tworzenia aplikacji Google Data Rails jest konfigurowanie kolejek. Zbliża się jednak czas na wdrożenie aplikacji. Zalecamy korzystanie z serwera mod_rails na serwerze Apache. Konfiguracja, instalacja i uruchomienie są bardzo łatwe. Możesz zacząć działać od razu.
Zasoby
- Lista interfejsów API danych Google
- Strona projektu Biblioteki danych Google Ruby
- Artykuł: Używanie Ruby z interfejsami API danych Google
- Pobierz Ruby
- Pobierz RubyGems i rails
Dodatek
Przykłady
Menedżer DocList to pełna próbka Ruby on Rails, która obejmuje tematy omówione w tym artykule. Pełny kod źródłowy jest dostępny w usłudze hostingowej.
Więcej przykładów
Pobierz listę dokumentów Google użytkownika za pomocą ClientClient.
#!/usr/bin/ruby
require 'rubygems'
require 'gdata'
require 'highline/import'
def user_input(prompt='> ', echo=true)
ask(prompt) {|q| q.echo = echo}
end
email = user_input('email: ')
pass = user_input('password: ', false)
client = GData::Client::DocList.new({:source => 'google-RailsArticleSample-v1'})
client.clientlogin(email, pass)
feed = client.get(client.authsub_scope + 'documents/private/full').to_xml
puts 'Listing all documents: --------------------'
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[/%3[aA](.*)$/, 1]
puts
end
Połącz usługę za pomocą interfejsów API listy dokumentów, kontaktów i arkuszy kalkulacyjnych. Ten przykład pokazuje użycie bezpiecznego uwierzytelniania Sub w RoR.
require 'gdata'
class YourController < ApplicationController
before_filter :authenticate_client
PRIVATE_KEY = '/path/to/private_key.pem'
DOCLIST_SCOPE = 'http://docs.google.com/feeds/'
CONTACTS_SCOPE = 'http://www.google.com/m8/feeds/'
SPREADSHEETS_SCOPE = 'http://spreadsheets.google.com/feeds/'
def authenticate_client
scopes = [DOCLIST_SCOPE, SPREADSHEETS_SCOPE, CONTACTS_SCOPE]
@client = GData::Client::Base.new({:authsub_scope => scopes.join(' '),
:source => 'google-RailsArticleSample-v1'})
if params[:token].nil? and session[:token].nil?
next_url = url_for :controller => self.controller_name, :action => self.action_name
secure = true
@authsub_link = @client.authsub_url(next_url, secure, true)
render :controller => 'your_controller', :action => 'your_action'
elsif params[:token] and session[:token].nil?
@client.authsub_token = params[:token]
@client.authsub_private_key = PRIVATE_KEY
session[:token] = @client.auth_handler.upgrade()
end
if session[:token]
@client.authsub_token = session[:token]
@client.authsub_private_key = PRIVATE_KEY # Make sure to set your private key for subsequent requests
end
end
def get_docs
@feed = @client.get(@client.authsub_scope + 'documents/private/full').to_xml
end
end
Tworzenie, edytowanie i usuwanie playlist w YouTube za pomocą tokena AuthSub.
#!/usr/bin/ruby require 'rubygems' require 'gdata' yt = GData::Client::YouTube.new({:source => 'google-RailsArticleSample-v1'}) yt.authsub_token = 'SESSION_TOKEN' yt.client_id = 'CLIENT_ID' yt.developer_key = 'DEVELOPER_KEY' # 1.) Creating a new playlist entry = <<-EOF <entry xmlns="http://www.w3.org/2005/Atom" xmlns:yt="http://gdata.youtube.com/schemas/2007"> <title type="text">Ruby Utility Unit Test</title> <summary>This is a test playlist.</summary> </entry> EOF response = yt.post('http://gdata.youtube.com/feeds/api/users/default/playlists', entry).to_xml # 2.) Updating the received playlist edit_uri = response.elements["link[@rel='edit']"].attributes['href'] response.elements['summary'].text = 'Updated description' response = yt.put(edit_uri, response.to_s).to_xml # 3.) Deleting the playlist yt.delete(edit_uri)
Przydatne polecenia dotyczące kolei
Jeśli tak jak ja, ale od jakiegoś czasu nie korzystasz z kolejek, poniżej znajdziesz listę poleceń, które warto zapamiętać.
- Aktualizowanie instalacji RubyGem
sudo gem update --system
- Zaktualizuj zainstalowane klejnoty
sudo gem update
- Tworzenie nowej linii kolejowej z MySQL jako bazy danych
rails -d mysql APP_NAME
- Uruchom serwer w wersji produkcyjnej na innym porcie
ruby script/server -p PORT -e production
- Czyszczenie plików dziennika
rake log:clear