Google Data on Rails

اریک بیدلمن، تیم Google Data APIs
فوریه 2009

معرفی

"روبی در لیست کتابخانه های مشتری کجاست؟"

همکارم جف فیشر با انگیزه اشتهای وحشیانه توسعه دهندگان ما و محبوبیت همیشگی Ruby on Rails (RoR)، یک کتابخانه ابزار Ruby را از اعماق آتشین Mount Doom ساخته است. توجه داشته باشید، این یک کتابخانه مشتری کامل نیست، اما اصولی مانند احراز هویت و دستکاری اولیه XML را کنترل می کند. همچنین از شما می خواهد که مستقیماً با فید Atom با استفاده از ماژول REXML و XPath کار کنید.

حضار

این مقاله برای توسعه دهندگانی است که علاقه مند به دسترسی به APIهای Google Data با استفاده از Ruby، به ویژه Ruby on Rails هستند. فرض بر این است که خواننده با زبان برنامه نویسی Ruby و چارچوب توسعه وب Rails آشنایی دارد. من برای اکثر نمونه ها بر روی API لیست اسناد تمرکز می کنم، اما همین مفاهیم را می توان برای هر یک از APIهای داده اعمال کرد.

شروع شدن

الزامات

نصب Google Data Ruby Utility Library

برای به دست آوردن کتابخانه، می توانید منبع کتابخانه را مستقیماً از میزبانی پروژه دانلود کنید یا جم را نصب کنید:

sudo gem install gdata

نکته : برای اندازه گیری خوب، gem list --local اجرا کنید تا مطمئن شوید که جم به درستی نصب شده است.

احراز هویت

ClientLogin

ClientLogin به برنامه شما اجازه می دهد تا به صورت برنامه ریزی شده کاربران را به حساب Google یا G Suite آنها وارد کند. پس از تأیید اعتبار کاربر، Google یک نشانه Auth صادر می‌کند تا در درخواست‌های API بعدی به آن ارجاع داده شود. رمز برای مدت زمان مشخصی معتبر باقی می ماند، که توسط هر سرویس Google که با آن کار می کنید تعریف شده است. به دلایل امنیتی و برای ارائه بهترین تجربه به کاربران خود، فقط باید هنگام توسعه برنامه های دسکتاپ نصب شده از ClientLogin استفاده کنید. برای برنامه های تحت وب، استفاده از AuthSub یا OAuth ترجیح داده می شود.

کتابخانه Ruby یک کلاس کلاینت برای هر یک از APIها دارد. به عنوان مثال، از قطعه کد زیر برای ورود به user@gmail.com به 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 دو کنترل کننده اضافی AuthSubTokenInfo و AuthSubRevokeToken را برای مدیریت توکن ها ارائه می دهد. AuthSubTokenInfo برای بررسی اعتبار یک توکن مفید است. AuthSubRevokeToken به کاربران این امکان را می دهد که دسترسی به داده های خود را قطع کنند. برنامه شما باید از AuthSubRevokeToken به عنوان بهترین روش استفاده کند. هر دو روش در کتابخانه روبی پشتیبانی می شوند.

برای استعلام فراداده یک نشانه:

client.auth_handler.info

برای لغو یک نشانه جلسه:

client.auth_handler.revoke

برای اطلاعات کامل در AuthSub، به مستندات کامل AuthSub Authentication for Web Applications مراجعه کنید.

OAuth

در زمان نوشتن این مقاله، OAuth به ماژول GData::Auth اضافه نشده است.

هنگام استفاده از پلاگین Rails oauth یا Ruby oauth gem، استفاده از OAuth در کتابخانه ابزار باید نسبتاً ساده باشد. در هر صورت، شما می خواهید یک شی GData::HTTP::Request ایجاد کنید و آن را به عنوان هدر Authorization تولید شده توسط هر کتابخانه ارسال کنید.

دسترسی به فیدها

GET (در حال واکشی داده ها)

هنگامی که یک شی کلاینت را تنظیم کردید، از متد get() آن برای پرس و جو کردن فید Google Data استفاده کنید. 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 به عنوان یک همکار به سند با 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 (به روز رسانی داده ها)

برای به روز رسانی داده ها در سرور، از روش 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 را از برنامه جدا می کند. خط دوم جم 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 را برای آپاچی به شدت توصیه می کنم. راه اندازی، نصب و اجرا بسیار آسان است. شما در کمترین زمان راه اندازی خواهید شد!

منابع

ضمیمه

مثال ها

DocList Manager یک نمونه کامل Ruby on Rails است که موضوعات مورد بحث در این مقاله را نشان می دهد. کد منبع کامل از میزبانی پروژه در دسترس است.