กุมภาพันธ์ 2009
บทนำ
"Ruby อยู่ตรงไหนในรายการไลบรารีของไคลเอ็นต์"
ด้วยความกระหายในการพัฒนาของนักพัฒนาแอปและRuby on Rails (RoR) ที่ได้รับความนิยมอย่างต่อเนื่อง เจฟฟ์ ฟิชเชอร์ เพื่อนร่วมงานของฉันจึงได้สร้างคลังยูทิลิตี Ruby จากภูเขาไฟมรณะ โปรดทราบว่านี่ไม่ใช่ไลบรารีไคลเอ็นต์แบบเต็ม แต่จะจัดการพื้นฐานต่างๆ เช่น การตรวจสอบสิทธิ์และการจัดการ XML ขั้นพื้นฐาน นอกจากนี้ คุณยังต้องทำงานกับฟีด Atom โดยตรงโดยใช้โมดูล REXML และ XPath
ผู้ชม
บทความนี้มีไว้สำหรับนักพัฒนาแอปที่สนใจเข้าถึง Google Data APIs โดยใช้ Ruby โดยเฉพาะ Ruby on Rails โดยถือว่าผู้อ่านมีความคุ้นเคยกับภาษาโปรแกรม Ruby และเฟรมเวิร์กการพัฒนาเว็บ Rails อยู่บ้าง เราจะเน้นที่ Documents List API สำหรับตัวอย่างส่วนใหญ่ แต่คุณสามารถนำแนวคิดเดียวกันนี้ไปใช้กับ Data API ใดก็ได้
เริ่มต้นใช้งาน
ข้อกำหนด
- Ruby 1.8.6 แพตช์ระดับ 114 ขึ้นไป ดาวน์โหลด
- RubyGems 1.3.1 ขึ้นไป ดาวน์โหลด
- Rails 2.2.2 ขึ้นไป ดาวน์โหลด
การติดตั้งไลบรารียูทิลิตี Google Data Ruby
หากต้องการรับไลบรารี คุณสามารถดาวน์โหลดแหล่งที่มาของไลบรารีโดยตรง จากการโฮสต์โปรเจ็กต์หรือติดตั้ง Gem ได้
sudo gem install gdata
เคล็ดลับ: เพื่อให้มั่นใจ ให้เรียกใช้ gem list --local
เพื่อยืนยันว่าได้ติดตั้ง Gem อย่างถูกต้อง
การตรวจสอบสิทธิ์
ClientLogin
ClientLogin ช่วยให้แอปพลิเคชันของคุณบันทึกการเข้าสู่ระบบของผู้ใช้ไปยังบัญชี Google หรือ G Suite ได้โดยอัตโนมัติ เมื่อตรวจสอบความถูกต้องของข้อมูลเข้าสู่ระบบของผู้ใช้แล้ว Google จะออกโทเค็นการให้สิทธิ์เพื่อใช้อ้างอิงในคำขอ API ที่ตามมา โทเค็นจะยังคงใช้งานได้ตามระยะเวลาที่กำหนด ซึ่งกำหนดโดยบริการของ Google ที่คุณกำลังใช้งาน ด้วยเหตุผลด้านความปลอดภัยและเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีที่สุด คุณควรใช้ ClientLogin เมื่อพัฒนาแอปพลิเคชันเดสก์ท็อปที่ติดตั้งแล้วเท่านั้น สำหรับเว็บแอปพลิเคชัน เราขอแนะนำให้ใช้ AuthSub หรือ OAuth
ไลบรารี Ruby มีคลาสไคลเอ็นต์สำหรับ API แต่ละรายการ ตัวอย่างเช่น ใช้ข้อมูลโค้ดต่อไปนี้เพื่อเข้าสู่ระบบ user@gmail.com
ไปยัง
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')
ดูรายการทั้งหมดของคลาสบริการที่ใช้งาน
หากบริการไม่มีคลาสไคลเอ็นต์ ให้ใช้คลาส GData::Client::Base
ตัวอย่างเช่น โค้ดต่อไปนี้จะบังคับให้ผู้ใช้เข้าสู่ระบบด้วยบัญชี 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)
หมายเหตุ: โดยค่าเริ่มต้น ไลบรารีจะใช้ HOSTED_OR_GOOGLE
สำหรับ accountType
ค่าที่เป็นไปได้คือ HOSTED_OR_GOOGLE
,
HOSTED
หรือ GOOGLE
ข้อเสียอย่างหนึ่งของการใช้ ClientLogin คือแอปพลิเคชันของคุณอาจได้รับคำถาม CAPTCHA เมื่อพยายามเข้าสู่ระบบไม่สำเร็จ หากเกิดกรณีดังกล่าว
คุณจะจัดการข้อผิดพลาดได้โดยเรียกใช้เมธอด clientlogin()
พร้อมพารามิเตอร์เพิ่มเติมต่อไปนี้
client.clientlogin(username, password, captcha_token, captcha_answer)
ดูข้อมูลเพิ่มเติมเกี่ยวกับการจัดการ CAPTCHA ได้ในเอกสารประกอบฉบับเต็มเกี่ยวกับการตรวจสอบสิทธิ์สำหรับแอปพลิเคชันที่ติดตั้ง
AuthSub
สร้าง 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)
โค้ดบล็อกก่อนหน้าจะสร้าง URL ต่อไปนี้ใน 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
นอกจากนี้ คุณยังใช้authsub_url
เมธอดของออบเจ็กต์ไคลเอ็นต์ได้ด้วย คลาสบริการแต่ละคลาสได้ตั้งค่าแอตทริบิวต์ authsub_scope
เริ่มต้นไว้แล้ว คุณจึงไม่จำเป็นต้องระบุค่าของคุณเอง
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)
โค้ดบล็อกก่อนหน้าจะสร้าง 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
การอัปเกรดโทเค็นแบบใช้ครั้งเดียวเป็นโทเค็นเซสชัน
AuthSub จะเปลี่ยนเส้นทางผู้ใช้กลับไปที่ http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN
เมื่อ
ผู้ใช้ให้สิทธิ์เข้าถึงข้อมูลของตน โปรดสังเกตว่า URL เป็นเพียง next_url
ของเราที่มีโทเค็นแบบใช้ครั้งเดียว
ต่อท้ายเป็นพารามิเตอร์การค้นหา
จากนั้นแลกโทเค็นแบบใช้ครั้งเดียวเป็นโทเค็นเซสชันที่มีอายุยาวนานโดยทำดังนี้
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]
Secure AuthSub มีลักษณะคล้ายกันมาก โดยสิ่งเดียวที่ต้องทำเพิ่มเติมคือการตั้งค่าคีย์ส่วนตัวก่อนอัปเกรดโทเค็น
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]
หมายเหตุ: หากต้องการใช้โทเค็นที่ปลอดภัย โปรดตรวจสอบว่าได้ตั้งค่า secure=true
เมื่อขอโทเค็นแบบใช้ครั้งเดียว โปรดดูการสร้าง URL ของ AuthSubRequest ด้านบน
การจัดการโทเค็น
AuthSub มีตัวแฮนเดิลเพิ่มเติม 2 รายการ ได้แก่ AuthSubTokenInfo และ
AuthSubRevokeToken สำหรับการจัดการโทเค็น AuthSubTokenInfo
มีประโยชน์ในการตรวจสอบ
ความถูกต้องของโทเค็น AuthSubRevokeToken
ให้ผู้ใช้เลือกหยุดการเข้าถึงข้อมูลของตนได้ แอปของคุณควรใช้ AuthSubRevokeToken
เป็นแนวทางปฏิบัติแนะนำ ไลบรารี Ruby รองรับทั้ง 2 วิธี
วิธีค้นหาข้อมูลเมตาของโทเค็น
client.auth_handler.info
วิธีเพิกถอนโทเค็นเซสชัน
client.auth_handler.revoke
ดูข้อมูลทั้งหมดเกี่ยวกับ AuthSub ได้ในเอกสารประกอบการตรวจสอบสิทธิ์ AuthSub สำหรับเว็บแอปพลิเคชันฉบับเต็ม
OAuth
ในขณะที่เขียนบทความนี้ เรายังไม่ได้เพิ่ม OAuth ลงในโมดูล GData::Auth
การใช้ OAuth ในไลบรารียูทิลิตีควรทำได้ง่ายเมื่อใช้ oauth-plugin ของ Rails หรือ oauth gem ของ Ruby ไม่ว่าจะในกรณีใด คุณจะต้องสร้างออบเจ็กต์ GData::HTTP::Request
และส่งส่วนหัว Authorization
ที่สร้างโดยแต่ละไลบรารี
การเข้าถึงฟีด
GET (ดึงข้อมูล)
เมื่อตั้งค่าออบเจ็กต์ไคลเอ็นต์แล้ว ให้ใช้วิธี get()
เพื่อค้นหาฟีดข้อมูล Google คุณใช้ XPath เพื่อ
ดึงข้อมูลองค์ประกอบ Atom ที่เฉพาะเจาะจงได้ ตัวอย่างการดึงข้อมูลเอกสาร Google ของผู้ใช้มีดังนี้
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 (สร้างข้อมูลใหม่)
ใช้เมธอด post()
ของไคลเอ็นต์เพื่อสร้างข้อมูลใหม่ในเซิร์ฟเวอร์ ตัวอย่างต่อไปนี้จะเพิ่ม
new_writer@example.com
เป็นผู้ทำงานร่วมกันในเอกสารที่มีรหัส 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 (การอัปเดตข้อมูล)
หากต้องการอัปเดตข้อมูลในเซิร์ฟเวอร์ ให้ใช้เมธอด put()
ของไคลเอ็นต์ ตัวอย่างต่อไปนี้จะอัปเดตชื่อเอกสาร
โดยจะถือว่าคุณมีฟีดจากคำค้นหาก่อนหน้านี้
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)
ลบ
หากต้องการลบ <atom:entry> หรือข้อมูลอื่นๆ ออกจากเซิร์ฟเวอร์ ให้ใช้วิธี delete()
ตัวอย่างต่อไปนี้จะลบเอกสาร โค้ดนี้ถือว่าคุณมีรายการเอกสาร
จากการค้นหาก่อนหน้า
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)
การสร้างแอปพลิเคชัน Rails ใหม่
โดยปกติแล้ว การสร้างแอป Rails ใหม่ครั้งแรกจะเกี่ยวข้องกับการเรียกใช้เครื่องมือสร้างโครงร่างเพื่อสร้างไฟล์ MVC
หลังจากนั้น ให้เรียกใช้ rake db:migrate
เพื่อตั้งค่าตารางฐานข้อมูล อย่างไรก็ตาม เนื่องจากแอปพลิเคชันของเราจะค้นหาข้อมูลจาก Google Documents List
API เราจึงไม่จำเป็นต้องใช้การจัดโครงสร้างหรือฐานข้อมูลทั่วไป แต่ให้สร้างแอปพลิเคชันและตัวควบคุมแบบง่ายใหม่แทน
rails doclist cd doclist ruby script/generate controller doclist
และทำการเปลี่ยนแปลงต่อไปนี้ใน config/environment.rb
config.frameworks -= [ :active_record, :active_resource, :action_mailer ] config.gem 'gdata', :lib => 'gdata'
บรรทัดแรกจะยกเลิกการเชื่อมต่อ ActiveRecord
จากแอปพลิเคชัน
บรรทัดที่ 2 จะโหลด Gem gdata
เมื่อเริ่มต้น
สุดท้าย ฉันเลือกที่จะเชื่อมต่อเส้นทางเริ่มต้น ('/
') กับการดำเนินการ documents
ใน DoclistController
เพิ่มบรรทัดนี้ลงใน config/routes.rb
map.root :controller => 'doclist', :action => 'all'
เริ่มตัวควบคุม
เนื่องจากเราไม่ได้สร้างโครงร่าง ให้เพิ่มการดำเนินการที่ชื่อ "all
" ลงใน
DoclistController
ใน app/controllers/doclist_controller.rb
ด้วยตนเอง
class DoclistController < ApplicationController def all @foo = 'I pity the foo!' end end
และสร้าง all.html.erb
ใน app/views/doclist/
โดยทำดังนี้
<%= @foo %>
เปิดเว็บเซิร์ฟเวอร์และเริ่มการพัฒนา
ตอนนี้คุณควรจะเริ่มเว็บเซิร์ฟเวอร์เริ่มต้นได้แล้วโดยเรียกใช้ ruby script/server
หากทุกอย่างเรียบร้อยดี การชี้เบราว์เซอร์ไปที่ http://localhost:3000/
ควรแสดง 'I pity the foo!
'
เคล็ดลับ: อย่าลืมนำ public/index.html
ออกหรือเปลี่ยนชื่อ
เมื่อทุกอย่างทำงานได้แล้ว ให้ดูที่ไฟล์สุดท้ายของฉัน
DoclistController
และ
ApplicationController
เพื่อดูเนื้อหา
ของโปรเจ็กต์ DocList Manager นอกจากนี้ คุณยังควรดูที่
ContactsController
ซึ่ง
จัดการการเรียกไปยัง Google Contacts API
บทสรุป
ส่วนที่ยากที่สุดในการสร้างแอป Google Data Rails คือการกำหนดค่า Rails แต่การติดตั้งใช้งาน แอปพลิเคชันก็สำคัญไม่แพ้กัน เราขอแนะนำให้ใช้ mod_rails สำหรับ Apache การตั้งค่า ติดตั้ง และเรียกใช้ทำได้ง่ายมาก คุณจะพร้อมใช้งานได้ในเวลาไม่นาน
แหล่งข้อมูล
- รายการ Google Data API
- หน้าโปรเจ็กต์ไลบรารียูทิลิตี Ruby ของ Google Data
- บทความ: การใช้ Ruby กับ Google Data APIs
- ดาวน์โหลด Ruby
- ดาวน์โหลด RubyGems และ Rails
ภาคผนวก
ตัวอย่าง
DocList Manager เป็นตัวอย่าง Ruby on Rails แบบเต็มที่แสดงให้เห็น หัวข้อที่กล่าวถึงในบทความนี้ ซอร์สโค้ดทั้งหมด พร้อมให้บริการจากโฮสติ้งโปรเจ็กต์