فوریه 2009
معرفی
"روبی در لیست کتابخانه های مشتری کجاست؟"
همکارم جف فیشر با انگیزه اشتهای وحشیانه توسعه دهندگان ما و محبوبیت همیشگی Ruby on Rails (RoR)، یک کتابخانه ابزار Ruby را از اعماق آتشین Mount Doom ساخته است. توجه داشته باشید، این یک کتابخانه مشتری کامل نیست، اما اصولی مانند احراز هویت و دستکاری اولیه XML را کنترل می کند. همچنین از شما می خواهد که مستقیماً با فید Atom با استفاده از ماژول REXML و XPath کار کنید.
حضار
این مقاله برای توسعه دهندگانی است که علاقه مند به دسترسی به APIهای Google Data با استفاده از Ruby، به ویژه Ruby on Rails هستند. فرض بر این است که خواننده با زبان برنامه نویسی Ruby و چارچوب توسعه وب Rails آشنایی دارد. من برای اکثر نمونه ها بر روی API لیست اسناد تمرکز می کنم، اما همین مفاهیم را می توان برای هر یک از APIهای داده اعمال کرد.
شروع شدن
الزامات
- دانلود وصله Ruby 1.8.6 سطح 114+
- دانلود RubyGems 1.3.1+
- Rails 2.2.2+ دانلود کنید
نصب 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 را برای آپاچی به شدت توصیه می کنم. راه اندازی، نصب و اجرا بسیار آسان است. شما در کمترین زمان راه اندازی خواهید شد!
منابع
- فهرست Google Data API
- صفحه پروژه کتابخانه Google Data Ruby Utility
- مقاله: استفاده از Ruby با Google Data API
- روبی را دانلود کنید
- RubyGems and Rails را دانلود کنید
ضمیمه
مثال ها
DocList Manager یک نمونه کامل Ruby on Rails است که موضوعات مورد بحث در این مقاله را نشان می دهد. کد منبع کامل از میزبانی پروژه در دسترس است.
نمونه های بیشتر
با استفاده از ClientLogin، فهرست کاربر از اسناد Google را بازیابی کنید.
#!/usr/bin/ruby
require 'rubygems'
require 'gdata'
require 'highline/import'
def user_input(prompt='> ', echo=true)
ask(prompt) {|q| q.echo = echo}
end
email = user_input('email: ')
pass = user_input('password: ', false)
client = GData::Client::DocList.new({:source => 'google-RailsArticleSample-v1'})
client.clientlogin(email, pass)
feed = client.get(client.authsub_scope + 'documents/private/full').to_xml
puts 'Listing all documents: --------------------'
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[/%3[aA](.*)$/, 1]
puts
end
با استفاده از فهرست اسناد، مخاطبین و APIهای صفحه گسترده، ترکیب را انجام دهید. این مثال استفاده از AuthSub ایمن در RoR را نشان می دهد.
require 'gdata'
class YourController < ApplicationController
before_filter :authenticate_client
PRIVATE_KEY = '/path/to/private_key.pem'
DOCLIST_SCOPE = 'http://docs.google.com/feeds/'
CONTACTS_SCOPE = 'http://www.google.com/m8/feeds/'
SPREADSHEETS_SCOPE = 'http://spreadsheets.google.com/feeds/'
def authenticate_client
scopes = [DOCLIST_SCOPE, SPREADSHEETS_SCOPE, CONTACTS_SCOPE]
@client = GData::Client::Base.new({:authsub_scope => scopes.join(' '),
:source => 'google-RailsArticleSample-v1'})
if params[:token].nil? and session[:token].nil?
next_url = url_for :controller => self.controller_name, :action => self.action_name
secure = true
@authsub_link = @client.authsub_url(next_url, secure, true)
render :controller => 'your_controller', :action => 'your_action'
elsif params[:token] and session[:token].nil?
@client.authsub_token = params[:token]
@client.authsub_private_key = PRIVATE_KEY
session[:token] = @client.auth_handler.upgrade()
end
if session[:token]
@client.authsub_token = session[:token]
@client.authsub_private_key = PRIVATE_KEY # Make sure to set your private key for subsequent requests
end
end
def get_docs
@feed = @client.get(@client.authsub_scope + 'documents/private/full').to_xml
end
end
ایجاد، ویرایش و حذف یک لیست پخش در YouTube با استفاده از یک نشانه AuthSub.
#!/usr/bin/ruby require 'rubygems' require 'gdata' yt = GData::Client::YouTube.new({:source => 'google-RailsArticleSample-v1'}) yt.authsub_token = 'SESSION_TOKEN' yt.client_id = 'CLIENT_ID' yt.developer_key = 'DEVELOPER_KEY' # 1.) Creating a new playlist entry = <<-EOF <entry xmlns="http://www.w3.org/2005/Atom" xmlns:yt="http://gdata.youtube.com/schemas/2007"> <title type="text">Ruby Utility Unit Test</title> <summary>This is a test playlist.</summary> </entry> EOF response = yt.post('http://gdata.youtube.com/feeds/api/users/default/playlists', entry).to_xml # 2.) Updating the received playlist edit_uri = response.elements["link[@rel='edit']"].attributes['href'] response.elements['summary'].text = 'Updated description' response = yt.put(edit_uri, response.to_s).to_xml # 3.) Deleting the playlist yt.delete(edit_uri)
دستورات مفید ریل
اگر شما هم مثل من هستید و مدتی است از Rails استفاده نکرده اید، در اینجا لیستی از دستورات وجود دارد که ارزش به خاطر سپردن دارد.
- نصب RubyGem خود را به روز کنید
-
sudo gem update --system
- سنگهای نصب شده را به روز کنید
-
sudo gem update
- یک Rails جدید با MySQL به عنوان db ایجاد کنید
-
rails -d mysql APP_NAME
- شروع به تولید سرور در پورت دیگری
-
ruby script/server -p PORT -e production
- فایل های لاگ خود را پاک کنید
-
rake log:clear