Data Google di Rails

Eric Bidelman, Tim Google Data API
Februari 2009

Pengantar

"Di mana Ruby dalam daftar library klien?"

Terinspirasi oleh keinginan kuat para developer kami dan popularitas Ruby on Rails (RoR) yang terus berlanjut, rekan saya Jeff Fisher telah membuat library utilitas Ruby dari kedalaman Gunung Doom yang berapi-api. Perlu diingat, ini bukan library klien yang lengkap, tetapi menangani hal-hal mendasar seperti autentikasi dan manipulasi XML dasar. Anda juga harus berinteraksi langsung dengan feed Atom menggunakan modul REXML dan XPath.

Audiens

Artikel ini ditujukan untuk developer yang tertarik mengakses Google Data API menggunakan Ruby, khususnya Ruby on Rails. Panduan ini mengasumsikan bahwa pembaca sudah memahami bahasa pemrograman Ruby dan framework pengembangan web Rails. Saya berfokus pada Documents List API untuk sebagian besar contoh, tetapi konsep yang sama dapat diterapkan ke Data API mana pun.

Memulai

Persyaratan

Menginstal Google Data Ruby Utility Library

Untuk mendapatkan library, Anda dapat mendownload sumber library secara langsung dari hosting project atau menginstal gem:

sudo gem install gdata

Tips: Untuk memastikan, jalankan gem list --local untuk memverifikasi bahwa gem telah diinstal dengan benar.

Autentikasi

ClientLogin

ClientLogin memungkinkan aplikasi Anda login pengguna ke akun Google atau G Suite mereka secara terprogram. Setelah memvalidasi kredensial pengguna, Google akan menerbitkan token Auth yang akan dirujuk dalam permintaan API berikutnya. Token tetap valid selama jangka waktu yang ditetapkan, yang ditentukan oleh layanan Google yang Anda gunakan. Untuk alasan keamanan dan untuk memberikan pengalaman terbaik kepada pengguna Anda, Anda hanya boleh menggunakan ClientLogin saat mengembangkan aplikasi desktop yang diinstal. Untuk aplikasi web, sebaiknya gunakan AuthSub atau OAuth.

Library Ruby memiliki class klien untuk setiap API. Misalnya, gunakan cuplikan kode berikut untuk login user@gmail.com ke 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')

Lihat daftar lengkap class layanan yang diterapkan. Jika layanan tidak memiliki class klien, gunakan class GData::Client::Base. Sebagai contoh, kode berikut memaksa pengguna untuk login dengan akun 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)

Catatan: Secara default, library menggunakan HOSTED_OR_GOOGLE untuk accountType. Nilai yang mungkin adalah HOSTED_OR_GOOGLE, HOSTED, atau GOOGLE.

Salah satu kekurangan menggunakan ClientLogin adalah aplikasi Anda dapat dikirimi verifikasi CAPTCHA saat upaya login gagal. Jika hal itu terjadi, Anda dapat menangani error dengan memanggil metode clientlogin() dengan parameter tambahannya: client.clientlogin(username, password, captcha_token, captcha_answer). Lihat dokumentasi Autentikasi untuk Aplikasi yang Diinstal lengkap untuk mengetahui informasi selengkapnya tentang cara menangani CAPTCHA.

AuthSub

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

Blok kode sebelumnya membuat URL berikut di 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

Anda juga dapat menggunakan metode authsub_url objek klien. Setiap class layanan telah menetapkan atribut authsub_scope default sehingga Anda tidak perlu menentukan atribut Anda sendiri.

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)

Blok kode sebelumnya akan membuat URL berikut:

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

Mengupgrade token sekali pakai menjadi token sesi

AuthSub akan mengalihkan pengguna kembali ke http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN setelah mereka memberikan akses ke data mereka. Perhatikan bahwa URL hanyalah next_url kami dengan token sekali pakai yang ditambahkan sebagai parameter kueri.

Selanjutnya, tukarkan token sekali pakai dengan token sesi yang berlaku lama:

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]

AuthSub yang aman sangat mirip. Satu-satunya tambahan adalah menyetel kunci pribadi Anda sebelum mengupgrade token:

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]

Catatan: Untuk menggunakan token aman, pastikan untuk menetapkan secure=true saat meminta token sekali pakai. Lihat Membuat URL AuthSubRequest di atas.

Pengelolaan token

AuthSub menyediakan dua handler tambahan, AuthSubTokenInfo dan AuthSubRevokeToken untuk mengelola token. AuthSubTokenInfo berguna untuk memeriksa validitas token. AuthSubRevokeToken memberi pengguna opsi untuk menghentikan akses ke data mereka. Aplikasi Anda harus menggunakan AuthSubRevokeToken sebagai praktik terbaik. Kedua metode tersebut didukung di library Ruby.

Untuk membuat kueri metadata token:

client.auth_handler.info

Untuk mencabut token sesi:

client.auth_handler.revoke

Lihat dokumentasi Autentikasi AuthSub untuk Aplikasi Web lengkap untuk mengetahui informasi lengkap tentang AuthSub.

OAuth

Pada saat penulisan artikel ini, OAuth belum ditambahkan ke modul GData::Auth.

Penggunaan OAuth di library utilitas akan relatif mudah jika menggunakan oauth-plugin Rails atau gem oauth Ruby. Dalam kedua kasus tersebut, Anda harus membuat objek GData::HTTP::Request dan meneruskan header Authorization yang dihasilkan oleh setiap library.

Mengakses feed

GET (mengambil data)

Setelah menyiapkan objek klien, gunakan metode get() untuk membuat kueri feed Data Google. XPath dapat digunakan untuk mengambil elemen Atom tertentu. Berikut adalah contoh pengambilan Dokumen Google pengguna:

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 (membuat data baru)

Gunakan metode post() klien untuk membuat data baru di server. Contoh berikut akan menambahkan new_writer@example.com sebagai kolaborator ke dokumen dengan ID: 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 (memperbarui data)

Untuk memperbarui data di server, gunakan metode put() klien. Contoh berikut akan memperbarui judul dokumen. Asumsinya Anda memiliki feed dari kueri sebelumnya.

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)

HAPUS

Untuk menghapus <atom:entry> atau data lain dari server, gunakan metode delete(). Contoh berikut akan menghapus dokumen. Kode mengasumsikan Anda memiliki entri dokumen dari kueri sebelumnya.

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)

Membuat aplikasi Rails baru

Biasanya latihan pertama dalam membuat aplikasi Rails baru melibatkan menjalankan generator kerangka untuk membuat file MVC Anda. Setelah itu, rake db:migrate akan berjalan untuk menyiapkan tabel database Anda. Namun, karena aplikasi kita akan mengkueri Google Documents List API untuk mendapatkan data, kita tidak terlalu memerlukan database atau scaffolding generik. Sebagai gantinya, buat aplikasi dan pengontrol sederhana baru:

rails doclist
cd doclist
ruby script/generate controller doclist

dan lakukan perubahan berikut pada config/environment.rb:

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

Baris pertama melepaskan ActiveRecord dari aplikasi. Baris kedua memuat gem gdata saat startup.

Terakhir, saya memilih untuk menghubungkan rute default ('/') ke tindakan documents di DoclistController. Tambahkan baris ini ke config/routes.rb:

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

Mulai pengontrol

Karena kita tidak membuat scaffolding, tambahkan tindakan bernama 'all' secara manual ke DoclistController di app/controllers/doclist_controller.rb.

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

dan buat all.html.erb di bawah app/views/doclist/:

<%= @foo %>

Mulai server web & mulai pengembangan

Sekarang Anda dapat memulai server web default dengan memanggil ruby script/server. Jika semuanya berjalan lancar, mengarahkan browser Anda ke http://localhost:3000/ akan menampilkan 'I pity the foo!'.

Tips: Jangan lupa untuk menghapus atau mengganti nama public/index.html.

Setelah semuanya berfungsi, lihat DoclistController dan ApplicationController akhir saya untuk inti project DocList Manager. Anda juga perlu melihat ContactsController, yang menangani panggilan ke Google Contacts API.

Kesimpulan

Bagian tersulit dalam membuat aplikasi Google Data Rails adalah mengonfigurasi Rails. Namun, yang kedua adalah men-deploy aplikasi Anda. Untuk itu, sebaiknya gunakan mod_rails untuk Apache. Penyiapan, penginstalan, dan pengoperasiannya sangat mudah. Anda akan siap menggunakannya dalam waktu singkat.

Resource

Lampiran

Contoh

DocList Manager adalah contoh Ruby on Rails lengkap yang menunjukkan topik yang dibahas dalam artikel ini. Kode sumber lengkap tersedia dari hosting project.