شباط (فبراير) 2009
المقدمة
"Where's Ruby is on the list of client مكتبات? "
بدافع من حماسة مطوّري البرامج وشعبية Ruby on السكك الحديدية (ROR) المتواصلة، أنشأ زميلي جيف فيشر مكتبة لمستلزمات لعبة Ruby من أعماق جبل Doom. ضع في اعتبارك أنها ليست مكتبة عميلة كاملة، ولكنها ستتعامل مع الأساسيات مثل المصادقة ومعالجة XML الأساسية. ويتطلّب ذلك أيضًا العمل مباشرةً مع خلاصة Atom باستخدام وحدة REXML وXPath.
الجمهور
هذه المقالة مُعدّة لمطوّري البرامج المهتمين بالوصول إلى واجهات برمجة تطبيقات بيانات Google باستخدام Ruby، خاصة Ruby على السكك الحديدية. وتفترض أنّ القارئ على دراية بلغة برمجة Ruby وإطار عمل تطوير خدمات "السكة الحديدية" على الويب. أركز على واجهة برمجة التطبيقات لقائمة المستندات لمعظم النماذج، ولكن يمكن تطبيق المفاهيم نفسها على أي من واجهات برمجة التطبيقات للبيانات.
البدء
المتطلّبات
- إصدار 1.8.6 لروبي من المستوى 114 أو أكثر تنزيل
- RubyGems 1.3.1 أو الأحدث تنزيل
- السكة الحديدية 2.2.2+ تنزيل
تثبيت مكتبة أداة Google Ruby في Google Data
للحصول على المكتبة، يمكنك إما تنزيل مصدر المكتبة مباشرة من استضافة المشروع أو تثبيت الأداة:
sudo gem install gdata
نصيحة: للحصول على قياس جيد، شغّل gem list --local
للتحقق من تثبيت الجوهرة بشكل صحيح.
المصادقة
ClientLogin
يتيح ClientLogin لتطبيقك تسجيل دخول المستخدمين آليًا إلى حساباتهم على Google أو G Suite. عند التحقق من بيانات اعتماد المستخدم، تصدر Google رمز مصادقة مميزًا لتتم الإشارة إليه في طلبات واجهة برمجة التطبيقات التالية. يظل الرمز المميز صالحًا لمدة زمنية محددة، يتم تحديدها من خلال أي خدمة من خدمات Google تعمل معها. لأسباب أمنية ولتوفير أفضل تجربة للمستخدمين، يجب ألا تستخدم ClientLogin إلا عند تطوير تطبيقات سطح المكتب المثبتة. بالنسبة إلى تطبيقات الويب، يُفضَّل استخدام AuthSub أو OAuth.
تحتوي مكتبة Ruby على فئة عميل لكل واجهة من واجهات برمجة التطبيقات. على سبيل المثال، استخدم مقتطف الرمز التالي لتسجيل الدخول user@gmail.com
إلى
واجهة برمجة التطبيقات لبيانات قائمة المستندات:
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 معالجَين إضافيَين، وهما AuthSubTokenInfo و
AuthSubإبطالToken لإدارة الرموز المميّزة. AuthSubTokenInfo
مفيد للتحقق من صلاحية الرمز المميز. تمنح خدمة AuthSubRevokeToken
المستخدمين خيار إيقاف الوصول إلى بياناتهم. ويجب أن يستخدم تطبيقك AuthSubRevokeToken
كأفضل ممارسة. تتوفّر كلتا الطريقتين في مكتبة Ruby.
للاستعلام عن البيانات الوصفية للرمز المميز:
client.auth_handler.info
لإبطال رمز مميز للجلسة:
client.auth_handler.revoke
اطلع على وثائق مصادقة AuthSub لتطبيقات الويب الكاملة لمعرفة التفاصيل الدقيقة حول AuthSub.
OAuth
أثناء كتابة هذه المقالة، لم تتم إضافة OAuth إلى الوحدة GData::Auth
.
يجب أن يكون استخدام OAuth في مكتبة المرافق واضحًا نسبيًا عند استخدام القضبان 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:أو إدخال آخر من البيانات من الخادم، استخدم طريقة 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)
إنشاء تطبيق جديد لخطوط السكك الحديدية
عادةً ما يتطلب الأمر الأول عند إنشاء تطبيق السكك الحديدية الجديد تشغيل مولدات السقالات لإنشاء ملفات MVC.
بعد ذلك، يتم تشغيل rake db:migrate
لإعداد جداول قاعدة البيانات. ومع ذلك، ونظرًا لأن تطبيقنا سيبحث في واجهة برمجة التطبيقات لقائمة مستندات 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
من التطبيق.
يعمل السطر الثاني على تحميل جوهرة 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".
الخاتمة
أصعب شيء في إنشاء تطبيق Google Datarails هو تهيئة Trains! ومع ذلك، تتمثّل الخطوة الثانية في نشر تطبيقك. ولذلك، أوصي بشدة باستخدام mod_rails لنظام Apache. من السهل جدًا إعداده وتثبيته وتشغيله. ستتمكن من البدء في وقت قصير!
الموارد
- قائمة بواجهات برمجة التطبيقات لبيانات Google
- صفحة مشروع مكتبة بيانات Google Ruby
- مقالة: استخدام Ruby مع Google Data APIs
- تنزيل Ruby
- تنزيل RubyGems وRrails
الملحق
أمثلة
يعتبر DocList Manager نموذجًا كاملاً لـ Ruby on السكك الحديدية يوضح الموضوعات التي تمت مناقشتها في هذه المقالة. تتوفر شفرة المصدر الكاملة من خلال استضافة المشروع.
مزيد من الأمثلة
استرد قائمة مستندات Google لأحد المستخدمين باستخدام ClientLogin.
#!/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
المزج باستخدام واجهة برمجة التطبيقات لقائمة المستندات وجهات الاتصال وجداول البيانات يوضح هذا المثال استخدام 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)
أوامر سكة حديد مفيدة
إذا كنت مثلي ولم تستخدم "السكك الحديدية" منذ مدة، فإليك قائمة بالأوامر التي تستحق تذكرها.
- تحديث تثبيت RubyGem
sudo gem update --system
- تحديث الجواهر المثبّتة
sudo gem update
- إنشاء خطوط سكك حديدية جديدة باستخدام MySQL كقاعدة بيانات
rails -d mysql APP_NAME
- بدء الخادم في مرحلة الإنتاج باستخدام منفذ آخر
ruby script/server -p PORT -e production
- محو ملفات السجلّ
rake log:clear