Google Data on Rails

Eric Bidelman, Google Data APIs Team
Şubat 2009

Giriş

"İstemci kitaplıkları listesinde Ruby nerede?"

Geliştiricilerimizin doymak bilmez iştahı ve Ruby on Rails'in (RoR) kalıcı popülaritesinden ilham alan iş arkadaşım Jeff Fisher, Ruby yardımcı kitaplığı oluşturdu. Bu kitaplık tam teşekküllü bir istemci kitaplığı olmasa da kimlik doğrulama ve temel XML işleme gibi temel işlevleri yerine getirir. Ayrıca, REXML modülünü ve XPath'i kullanarak doğrudan Atom feed'iyle çalışmanız gerekir.

Kitle

Bu makale, Google Veri API'lerine Ruby (özellikle Ruby on Rails) kullanarak erişmek isteyen geliştiriciler için hazırlanmıştır. Okuyucunun Ruby programlama dili ve Rails web geliştirme çerçevesi hakkında bilgi sahibi olduğu varsayılır. Çoğu örnekte Documents List API'ye odaklanıyorum ancak aynı kavramlar Data API'lerin herhangi birinde de uygulanabilir.

Başlarken

Şartlar

Google Data Ruby Utility Library'yi yükleme

Kitaplığı edinmek için doğrudan proje barındırma hizmetinden kitaplık kaynağını indirebilir veya gem'i yükleyebilirsiniz:

sudo gem install gdata

İpucu: Gem'in düzgün şekilde yüklendiğini doğrulamak için gem list --local komutunu çalıştırmanız önerilir.

Kimlik doğrulama

ClientLogin

ClientLogin, uygulamanızın kullanıcıları Google veya G Suite hesaplarına programatik olarak giriş yapmasına olanak tanır. Google, kullanıcının kimlik bilgilerini doğruladıktan sonra sonraki API isteklerinde referans olarak kullanılacak bir kimlik doğrulama jetonu yayınlar. Jeton, çalıştığınız Google hizmeti tarafından tanımlanan belirli bir süre boyunca geçerli kalır. Güvenlik nedeniyle ve kullanıcılarınıza en iyi deneyimi sunmak için ClientLogin'i yalnızca yüklü masaüstü uygulamaları geliştirirken kullanmalısınız. Web uygulamaları için AuthSub veya OAuth kullanılması tercih edilir.

Ruby kitaplığında, API'lerin her biri için bir istemci sınıfı bulunur. Örneğin, Doküman Listesi Veri API'sine user@gmail.com giriş yapmak için aşağıdaki kod snippet'ini kullanın:

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')

Uygulanan hizmet sınıflarının tam listesini inceleyin. Bir hizmetin istemci sınıfı yoksa GData::Client::Base sınıfını kullanın. Örneğin, aşağıdaki kod kullanıcıları bir G Suite hesabıyla giriş yapmaya zorlar.

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)

Not: Kitaplık, varsayılan olarak accountType için HOSTED_OR_GOOGLE kullanır. Olası değerler HOSTED_OR_GOOGLE, HOSTED veya GOOGLE'dir.

ClientLogin kullanmanın dezavantajlarından biri, uygulamanıza başarısız giriş denemelerinde CAPTCHA testleri gönderilebilmesidir. Bu durumda, clientlogin() yöntemini ek parametreleriyle birlikte çağırarak hatayı işleyebilirsiniz: client.clientlogin(username, password, captcha_token, captcha_answer). CAPTCHA'larla ilgili daha fazla bilgi için Yüklü Uygulamalar İçin Kimlik Doğrulama dokümanının tamamını inceleyin.

AuthSub

AuthSubRequest URL'sini oluşturma

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)

Önceki kod bloğu, authsub_link içinde aşağıdaki URL'yi oluşturur:

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

authsub_url yöntemini de kullanabilirsiniz. Her hizmet sınıfı için varsayılan bir authsub_scope özelliği ayarlanmıştır. Bu nedenle, kendi özelliğinizi belirtmeniz gerekmez.

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)

Önceki kod bloğu aşağıdaki URL'yi oluşturur:

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

Tek kullanımlık jetonu oturum jetonuna yükseltme

AuthSub, kullanıcı verilerine erişim izni verdikten sonra kullanıcıyı http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN adresine yönlendirir. URL'nin, tek kullanımlık jetonun sorgu parametresi olarak eklendiği next_url olduğunu unutmayın.

Ardından, tek kullanımlık jetonu uzun süreli bir oturum jetonuyla değiştirin:

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]

Güvenli AuthSub da benzer bir şekilde çalışır. Tek ekleme, jetonu yükseltmeden önce özel anahtarınızı ayarlamaktır:

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]

Not: Güvenli jetonları kullanmak için tek kullanımlık jeton isteğinde bulunurken secure=true değerini ayarladığınızdan emin olun. Yukarıdaki AuthSubRequest URL'sini oluşturma bölümünü inceleyin.

Jeton yönetimi

AuthSub, jetonları yönetmek için iki ek işleyici (AuthSubTokenInfo ve AuthSubRevokeToken) sağlar. AuthSubTokenInfo, jetonun geçerliliğini kontrol etmek için kullanılır. AuthSubRevokeToken, kullanıcılara verilerine erişimi durdurma seçeneği sunar. Uygulamanızda en iyi uygulama olarak AuthSubRevokeToken kullanılmalıdır. Her iki yöntem de Ruby kitaplığında desteklenir.

Bir jetonun meta verilerini sorgulamak için:

client.auth_handler.info

Oturum jetonunu iptal etmek için:

client.auth_handler.revoke

AuthSub hakkında tüm bilgileri Web Uygulamaları için AuthSub Kimlik Doğrulaması belgelerinde bulabilirsiniz.

OAuth

Bu makalenin yazıldığı sırada OAuth, GData::Auth modülüne eklenmemişti.

Rails oauth-plugin veya Ruby oauth gem kullanılırken yardımcı program kitaplığında OAuth kullanmak nispeten kolaydır. Her iki durumda da bir GData::HTTP::Request nesnesi oluşturup her kitaplık tarafından oluşturulan Authorization üstbilgisini bu nesneye iletmeniz gerekir.

Feed'lere erişme

GET (veri getirme)

Bir istemci nesnesi ayarladıktan sonra, Google Veri feed'ini sorgulamak için bu nesnenin get() yöntemini kullanın. XPath, belirli Atom öğelerini almak için kullanılabilir. Aşağıda, bir kullanıcının Google Dokümanları'nı alma örneği verilmiştir:

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 (yeni veri oluşturma)

Sunucuda yeni veriler oluşturmak için istemcinin post() yöntemini kullanın. Aşağıdaki örnekte, new_writer@example.com kimlikli dokümana düzenleyen kişi olarak doc_id eklenir.

# 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 (verileri güncelleme)

Sunucudaki verileri güncellemek için istemcinin put() yöntemini kullanın. Aşağıdaki örnekte, bir dokümanın başlığı güncellenir. Önceki bir sorgudan feed'iniz olduğu varsayılır.

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)

SİL

Sunucudan bir <atom:entry> öğesini veya diğer verileri silmek için delete() yöntemini kullanın. Aşağıdaki örnekte bir doküman silinir. Kod, önceki bir sorgudan bir doküman girişi aldığınızı varsayar.

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)

Yeni bir Rails uygulaması oluşturma

Genellikle yeni bir Rails uygulaması oluştururken ilk olarak MVC dosyalarınızı oluşturmak için iskele oluşturma işlemleri çalıştırılır. Ardından, veritabanı tablolarınızı oluşturmak için rake db:migrate komutu çalıştırılır. Ancak uygulamamız veriler için Google Doküman Listesi API'sini sorgulayacağından genel iskele veya veritabanlarına pek ihtiyacımız yoktur. Bunun yerine yeni bir uygulama ve basit denetleyici oluşturun:

rails doclist
cd doclist
ruby script/generate controller doclist

ve config/environment.rb üzerinde aşağıdaki değişiklikleri yapın:

config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
config.gem 'gdata', :lib => 'gdata'

İlk satır, ActiveRecord uygulamasının bağlantısını kaldırır. İkinci satır, başlangıçta gdata gem'ini yükler.

Son olarak, varsayılan rotayı ("/") DoclistController içindeki documents işlemine bağlamayı seçtim. config/routes.rb dosyasına şu satırı ekleyin:

map.root :controller => 'doclist', :action => 'all'

Kumanda başlatma

İskele oluşturmadığımız için all adlı bir işlemi app/controllers/doclist_controller.rb içindeki DoclistController'e manuel olarak ekleyin.

class DoclistController < ApplicationController
  def all
    @foo = 'I pity the foo!'
  end
end

ve app/views/doclist/ altında all.html.erb oluşturun:

<%= @foo %>

Web sunucusunu başlatma ve geliştirmeye başlama

Artık ruby script/server komutunu çağırarak varsayılan web sunucusunu başlatabilirsiniz. Her şey yolundaysa tarayıcınızı http://localhost:3000/ adresine yönlendirdiğinizde "I pity the foo!" ifadesi gösterilir.

İpucu: public/index.html öğesini kaldırmayı veya yeniden adlandırmayı unutmayın.

Her şey çalışır duruma geldiğinde, DocList Manager projesinin esas kısmı için son DoclistController ve ApplicationController dosyalarıma göz atın. Ayrıca, Google Kişiler API'sine yapılan çağrıları işleyen ContactsController'ye de bakmak isteyebilirsiniz.

Sonuç

Google Data Rails uygulaması oluşturmanın en zor kısmı Rails'i yapılandırmaktır. Ancak ikinci en önemli adım, uygulamanızı dağıtmaktır. Bu amaçla Apache için mod_rails'i kesinlikle öneririz. Kurulumu, yüklemesi ve çalıştırması çok kolaydır. Kısa sürede kullanmaya başlayabilirsiniz.

Kaynaklar

Ek

Örnekler

DocList Manager, bu makalede ele alınan konuları gösteren tam bir Ruby on Rails örneğidir. Tam kaynak kodu, proje barındırma hizmetinden edinilebilir.