פברואר 2009
מבוא
"Where's Ruby on the list of client libraries?" (איפה Ruby ברשימה של ספריות לקוח?)
ההתלהבות של המפתחים שלנו והפופולריות המתמשכת של Ruby on Rails (RoR) הניעו אותי ואת הקולגה שלי, ג'ף פישר, ליצור ספריית כלי עזר ל-Ruby ממעמקי הר הגורל. חשוב לציין שזו לא ספריית לקוח מלאה, אבל היא מטפלת בפעולות בסיסיות כמו אימות ומניפולציה בסיסית של XML. בנוסף, צריך לעבוד ישירות עם פיד Atom באמצעות מודול REXML ו-XPath.
קהל
המאמר הזה מיועד למפתחים שרוצים לגשת אל Google Data APIs באמצעות Ruby, ובאופן ספציפי באמצעות Ruby on Rails. המדריך מניח שלקוראים יש היכרות מסוימת עם שפת התכנות Ruby ועם מסגרת פיתוח האינטרנט Rails. ברוב הדוגמאות אני מתמקד ב-Documents List API, אבל אפשר להשתמש באותם עקרונות בכל אחד מממשקי Data API.
תחילת העבודה
דרישות
התקנה של ספריית כלי השירות של Google Data Ruby
כדי לקבל את הספרייה, אפשר להוריד את מקור הספרייה ישירות מאירוח הפרויקט או להתקין את ה-gem:
sudo gem install gdata
טיפ: כדי לוודא שה-gem הותקן בצורה תקינה, מריצים את הפקודה gem list --local
.
אימות
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]
הגרסה המאובטחת של 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 מספק שני רכיבי handler נוספים, AuthSubTokenInfo ו-AuthSubRevokeToken, לניהול טוקנים. הפרמטר AuthSubTokenInfo
שימושי לבדיקת התוקף של טוקן. AuthSubRevokeToken
מאפשרת למשתמשים להפסיק את הגישה לנתונים שלהם. מומלץ להשתמש ב-AuthSubRevokeToken
באפליקציה. שתי השיטות נתמכות בספריית Ruby.
כדי לשלוח שאילתה לגבי המטא-נתונים של טוקן:
client.auth_handler.info
כדי לבטל טוקן של סשן:
client.auth_handler.revoke
במסמכי התיעוד המלאים בנושא אימות AuthSub לאפליקציות אינטרנט אפשר לקרוא את כל הפרטים על AuthSub.
OAuth
בזמן כתיבת המאמר הזה, פרוטוקול OAuth לא נוסף למודול GData::Auth
.
השימוש ב-OAuth בספריית כלי העזר אמור להיות פשוט יחסית כשמשתמשים ב-Rails oauth-plugin או ב-Ruby oauth gem. בכל מקרה, כדאי ליצור אובייקט 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 חדשה כולל הפעלה של מחוללי ה-scaffold כדי ליצור את קובצי ה-MVC.
לאחר מכן, המערכת מפעילה את rake db:migrate
כדי להגדיר את טבלאות מסד הנתונים. עם זאת, מכיוון שהאפליקציה שלנו תבצע שאילתות ב-API של רשימת המסמכים של Google כדי לאחזר נתונים, אין לנו צורך רב בפיגומים או במסדי נתונים גנריים. במקום זאת, יוצרים אפליקציה חדשה ובקר פשוט:
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
לאפליקציה.
השורה השנייה טוענת את ה-gem gdata
בהפעלה.
לבסוף, בחרתי לחבר את מסלול ברירת המחדל ('/
') לפעולה documents
ב-DoclistController
.
מוסיפים את השורה הזו אל config/routes.rb
:
map.root :controller => 'doclist', :action => 'all'
הפעלת בקר
לא יצרנו scaffolding, צריך להוסיף ידנית פעולה בשם '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 Workspace.
משאבים
- רשימה של Google Data APIs
- דף הפרויקט של Google Data Ruby Utility Library
- מאמר: שימוש ב-Ruby עם Google Data APIs
- הורדת Ruby
- הורדה של RubyGems ו-Rails
נספח
דוגמאות
DocList Manager הוא דוגמה מלאה של Ruby on Rails שממחישה את הנושאים שנדונים במאמר הזה. קוד המקור המלא זמין באירוח הפרויקט.