Dữ liệu của Google về đường sắt

Eric Bidelman, Nhóm API dữ liệu của Google
Tháng 2 năm 2009

Giới thiệu

" Ruby ở đâu trong danh sách client library?"

Nhờ sự thích thú mãnh liệt của các nhà phát triển và sự nổi tiếng lâu dài của Ruby on Rails (RoR), đồng nghiệp của tôi, Jeff Fisher đã tạo dựng một thư viện tiện ích Ruby từ độ sâu tối đa của Núi Doom. Xin lưu ý rằng đây không phải là một thư viện ứng dụng đầy đủ, nhưng xử lý các nguyên tắc cơ bản như xác thực và thao tác XML cơ bản. Ngoài ra, mô-đun này cũng yêu cầu bạn làm việc trực tiếp với nguồn cấp dữ liệu Atom bằng cách sử dụng mô-đun REXML và đích.

Đối tượng người xem

Bài viết này dành cho những nhà phát triển quan tâm đến việc truy cập API dữ liệu của Google bằng Ruby, cụ thể là Ruby on Rails. Phương thức này giả định rằng người đọc đã quen thuộc với ngôn ngữ lập trình Ruby và khung phát triển web của Rails. Tôi tập trung vào API danh sách tài liệu cho hầu hết các mẫu, nhưng có thể áp dụng các khái niệm tương tự cho bất kỳ API dữ liệu nào.

Bắt đầu

Yêu cầu

Cài đặt Thư viện tiện ích Ruby dữ liệu của Google

Để lấy thư viện, bạn có thể tải nguồn thư viện xuống trực tiếp từ dự án lưu trữ hoặc cài đặt thư viện:

sudo gem install gdata

Mẹo: Để đo lường chính xác, hãy chạy gem list --local để xác minh rằng thư viện đã được cài đặt đúng cách.

Xác thực

ClientLogin

ClientLogin cho phép ứng dụng của bạn đăng nhập theo cách có lập trình vào tài khoản Google hoặc G Suite của họ. Khi xác thực thông tin đăng nhập của người dùng, Google sẽ phát hành một Mã thông báo xác thực để tham chiếu trong các yêu cầu API tiếp theo. Mã thông báo này vẫn có hiệu lực trong một khoảng thời gian nhất định, được xác định theo dịch vụ bất kỳ của Google mà bạn đang sử dụng. Vì lý do bảo mật và để cung cấp cho người dùng trải nghiệm tốt nhất, bạn chỉ nên sử dụng ClientLogin khi phát triển các ứng dụng được cài đặt và dành cho máy tính. Đối với các ứng dụng web, bạn nên sử dụng AuthSub hoặc OAuth.

Thư viện Ruby có một lớp ứng dụng cho mỗi API. Ví dụ: sử dụng đoạn mã sau để đăng nhập user@gmail.com vào API dữ liệu danh sách tài liệu:

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')

Xem danh sách đầy đủ các lớp dịch vụ được triển khai. Nếu một dịch vụ không có lớp ứng dụng, hãy sử dụng lớp GData::Client::Base. Ví dụ: mã sau đây buộc người dùng đăng nhập bằng tài khoản 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)

Lưu ý: Theo mặc định, thư viện sử dụng HOSTED_OR_GOOGLE cho accountType. Giá trị có thể là HOSTED_OR_GOOGLE, HOSTED hoặc GOOGLE.

Một trong những nhược điểm của việc sử dụng ClientLogin là ứng dụng của bạn có thể bị gửi hình ảnh xác thực CAPTCHA trên các lần đăng nhập không thành công. Nếu điều đó xảy ra, bạn có thể xử lý lỗi bằng cách gọi phương thức clientlogin() kèm theo các tham số bổ sung: client.clientlogin(username, password, captcha_token, captcha_answer). Tham khảo tài liệu Xác thực ứng dụng đã cài đặt đầy đủ để biết thêm thông tin về cách xử lý CAPTCHA.

AuthSub

Tạo 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)

Khối mã trước đó tạo URL sau trong 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

Bạn cũng có thể sử dụng phương thức authsub_url của đối tượng ứng dụng. Mỗi lớp dịch vụ đã đặt một thuộc tính authsub_scope mặc định nên bạn không cần chỉ định thuộc tính của riêng mình.

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)

Khối mã trước đó tạo URL sau:

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

Nâng cấp mã thông báo sử dụng một lần lên mã thông báo phiên

AuthSub sẽ chuyển hướng người dùng quay lại http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN sau khi họ cấp quyền truy cập vào dữ liệu của mình. Vui lòng lưu ý URL chỉ là next_url của chúng tôi với mã thông báo sử dụng một lần được thêm vào dưới dạng tham số truy vấn.

Tiếp theo, hãy đổi mã thông báo dùng một lần để có mã thông báo phiên hoạt động dài hạn:

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 an toàn rất giống nhau. Việc bổ sung duy nhất là đặt khóa riêng tư của bạn trước khi nâng cấp mã thông báo:

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]

Lưu ý: Để sử dụng mã thông báo an toàn, hãy nhớ đặt secure=true khi yêu cầu mã thông báo sử dụng một lần. Xem Tạo URL AuthSubRequest ở trên.

Quản lý mã thông báo

AuthSub cung cấp thêm hai trình xử lý, AuthSubTokenInfoAuthSubRevocationToken để quản lý các mã thông báo. AuthSubTokenInfo rất hữu ích trong việc kiểm tra tính hợp lệ của mã thông báo. AuthSubRevokeToken cho phép người dùng ngừng truy cập vào dữ liệu của họ. Ứng dụng của bạn nên sử dụng AuthSubRevokeToken là phương pháp hay nhất. Cả hai phương thức đều được hỗ trợ trong thư viện Ruby.

Để truy vấn siêu dữ liệu của mã thông báo:

client.auth_handler.info

Cách thu hồi mã thông báo phiên:

client.auth_handler.revoke

Xem tài liệu đầy đủ về Xác thực AuthSub cho ứng dụng web để biết đầy đủ thông tin về AuthSub.

OAuth

Tại thời điểm viết bài viết này, OAuth chưa được thêm vào mô-đun GData::Auth.

Việc sử dụng OAuth trong thư viện tiện ích phải tương đối đơn giản khi sử dụng OAuth-plugin hoặc Ruby OAuth Trong cả hai trường hợp, bạn sẽ cần tạo đối tượng GData::HTTP::Request và truyền đối tượng đó vào tiêu đề Authorization mà mỗi thư viện tạo ra.

Truy cập vào nguồn cấp dữ liệu

GET (tìm nạp dữ liệu)

Sau khi bạn thiết lập đối tượng khách hàng, hãy sử dụng phương thức get() của đối tượng đó để truy vấn nguồn cấp dữ liệu của Google. suất mùa của JavaScript có thể dùng để truy xuất các phần tử Atom cụ thể. Sau đây là ví dụ về cách truy xuất Tài liệu Google của người dùng:

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 (tạo dữ liệu mới)

Sử dụng phương thức post() của ứng dụng để tạo dữ liệu mới trên máy chủ. Ví dụ sau sẽ thêm new_writer@example.com làm cộng tác viên vào tài liệu có mã nhận dạng: 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 (cập nhật dữ liệu)

Để cập nhật dữ liệu trên máy chủ, hãy sử dụng phương thức put() của ứng dụng. Ví dụ sau sẽ cập nhật tiêu đề của tài liệu. Giả sử bạn có một nguồn cấp dữ liệu qua truy vấn trước đó.

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)

DELETE

Để xoá <atom:entry> hoặc dữ liệu khác khỏi máy chủ, hãy sử dụng phương thức delete(). Ví dụ sau đây sẽ xoá một tài liệu. Mã giả định bạn có một mục nhập tài liệu từ truy vấn trước đó.

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)

Tạo ứng dụng Rails mới

Thông thường, bài tập đầu tiên để tạo ứng dụng Rails mới là chạy trình tạo scaffold để tạo tệp MVC. Sau đó, trình duyệt này sẽ chạy rake db:migrate để thiết lập bảng cơ sở dữ liệu. Tuy nhiên, vì ứng dụng của chúng tôi sẽ truy vấn API Danh sách tài liệu của Google để tạo dữ liệu, nên chúng tôi không cần phải có giàn giáo hoặc cơ sở dữ liệu chung. Thay vào đó, hãy tạo một ứng dụng mới và tay điều khiển đơn giản:

rails doclist
cd doclist
ruby script/generate controller doclist

và thực hiện các thay đổi sau đối với config/environment.rb:

config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
config.gem 'gdata', :lib => 'gdata'

Dòng đầu tiên ngắt kết nối ActiveRecord khỏi ứng dụng. Dòng thứ hai tải đá quý gdata khi khởi động.

Cuối cùng, tôi chọn kết nối tuyến đường mặc định ("/") với thao tác documents trong DoclistController. Thêm dòng này vào config/routes.rb:

map.root :controller => 'doclist', :action => 'all'

Khởi động bộ điều khiển

Vì chúng ta không tạo giàn giáo, nên hãy thêm một thao tác có tên là "all" vào DoclistController theo cách thủ công trong app/controllers/doclist_controller.rb.

class DoclistController < ApplicationController
  def all
    @foo = 'I pity the foo!'
  end
end

và tạo all.html.erb trong app/views/doclist/:

<%= @foo %>

Kích hoạt máy chủ web và bắt đầu phát triển

Bây giờ, bạn có thể khởi động máy chủ web mặc định bằng cách gọi ruby script/server. Nếu tất cả đều ổn, việc trỏ trình duyệt của bạn đến http://localhost:3000/ sẽ hiển thị 'I pity the foo!'.

Mẹo: Đừng quên xóa hoặc đổi tên public/index.html.

Sau khi bạn đã thực hiện được mọi việc, hãy xem DoclistControllerApplicationController cuối cùng của tôi về thịt của dự án Trình quản lý danh sách. Bạn cũng nên xem ContactsController để xử lý các lệnh gọi đến API Danh bạ Google.

Kết luận

Phần khó nhất trong việc tạo ứng dụng Google Data Rails là định cấu hình Rails! Tuy nhiên, giây đầy đủ là việc triển khai ứng dụng. Do đó, tôi thực sự khuyên bạn nên sử dụng mod_rails cho Apache. Việc thiết lập, cài đặt và chạy ứng dụng rất dễ dàng. Bạn có thể hoạt động ngay lập tức!

Tài nguyên

Phụ lục

Ví dụ

Trình quản lý danh sách DocList là một mẫu Ruby on Rails đầy đủ minh hoạ các chủ đề được thảo luận trong bài viết này. Bạn có thể sử dụng mã nguồn đầy đủ để lưu trữ dự án.