2009-04-14 30 views
54

Tôi muốn viết một ứng dụng Ruby on Rails tiêu thụ một API dịch vụ web RESTful thực hiện một số logic trên kết quả và sau đó hiển thị dữ liệu đó trên quan điểm của tôi. Ví dụ, giả sử tôi muốn viết một chương trình đã thực hiện tìm kiếm trên search.twitter.com. Sử dụng ruby ​​tinh khiết tôi có thể tạo ra các phương pháp sau đây:Cách "Rails Way" thích hợp để sử dụng dịch vụ web RESTful trên một tên miền khác là gì?

def run(search_term='', last_id=0) 
    @results = [] 
    url = URI.parse("http://search.twitter.com") 
    res = Net::HTTP.start(url.host, url.port) do |http| 
    http.get("/search.json?q=#{search_term}&since_id=#{last_id.to_s}") 
    end 
    @results = JSON.parse res.body 
end 

Tôi bị cám dỗ để chỉ cần thả phương pháp đó vào bộ điều khiển Rails của tôi như là một phương pháp tư nhân, nhưng một phần của tôi nghĩ rằng có một tốt hơn, nhiều hơn "Rails" cách để làm điều này. Có cách tiếp cận thực hành tốt nhất hay đây thực sự là cách tốt nhất?

Trả lời

51

Có một plugin/gem được gọi là HTTParty mà tôi đã sử dụng cho một số dự án.

http://johnnunemaker.com/httparty/

HTTParty phép bạn dễ dàng tiêu thụ bất kỳ dịch vụ web và phân tích kết quả vào một hash cho bạn. Sau đó, bạn có thể sử dụng chính băm hoặc khởi tạo một hoặc nhiều trường hợp mô hình với kết quả. Tôi đã làm theo cả hai cách.

Đối với ví dụ twitter, mã của bạn sẽ trông như thế này:

class Twitter 
    include HTTParty 
    base_uri 'twitter.com' 

    def initialize(u, p) 
    @auth = {:username => u, :password => p} 
    end 

    # which can be :friends, :user or :public 
    # options[:query] can be things like since, since_id, count, etc. 
    def timeline(which=:friends, options={}) 
    options.merge!({:basic_auth => @auth}) 
    self.class.get("/statuses/#{which}_timeline.json", options) 
    end 

    def post(text) 
    options = { :query => {:status => text}, :basic_auth => @auth } 
    self.class.post('/statuses/update.json', options) 
    end 
end 

# usage examples. 
twitter = Twitter.new('username', 'password') 
twitter.post("It's an HTTParty and everyone is invited!") 
twitter.timeline(:friends, :query => {:since_id => 868482746}) 
twitter.timeline(:friends, :query => 'since_id=868482746') 

Là một điểm cuối cùng, bạn có thể sử dụng mã của bạn ở trên cũng có, nhưng chắc chắn bao gồm mã trong một mô hình như trái ngược với một bộ điều khiển.

+0

Tôi thích đá quý này. Điều này làm cho dịch vụ web tiêu thụ thực sự trơn tru. Một câu hỏi tôi vẫn có mặc dù là Rails có một cái gì đó được xây dựng trong đã làm điều này? Có vẻ như đây là một điều đủ phổ biến để cố gắng làm điều đó họ sẽ có một cách để làm điều đó. –

+0

Ngoài ra, hãy tha thứ cho Rails noobieness của tôi :), làm thế nào tôi có thể thiết lập nó như một mô hình. Tôi chỉ sử dụng các mô hình để truy cập cơ sở dữ liệu bằng ActiveRecord. –

+7

Không có bất kỳ thứ gì được tích hợp vào lõi ray. Mô hình chỉ là một lớp - chỉ cần tạo một lớp trong thư mục mô hình và không kế thừa từ lớp ActiveRecord: Base. Bạn sẽ không có bất kỳ sự tốt đẹp AR bao gồm, nhưng đây là một mô hình khá phổ biến cho việc tiêu thụ các dịch vụ web trong một ứng dụng đường ray –

11

nếu dịch vụ web RESTful từ xa cũng được tạo bằng Ruby on Rails, ActiveResource là cách để thực hiện.

+0

tôi không thể đưa ra giả thuyết rằng khi tôi muốn kéo dữ liệu từ nhiều trang web khác nhau trong đó tôi sẽ không có ý tưởng những gì khuôn khổ cơ bản sẽ. Nhưng tôi sẽ xem xét ActiveResource cho những thứ tôi biết là Rails. Cảm ơn! –

+4

Trên thực tế, dịch vụ RESTful từ xa không phải được tạo bằng cách sử dụng Rails cho ActiveResource để hoạt động. Việc triển khai cơ bản không quan trọng. – WattsInABox

+0

Điều này chắc chắn là cách ưa thích của Rails để tiêu thụ tài nguyên RESTful. Giữ mã sạch sẽ và phù hợp với MVC. –

2

Để trả lời ví dụ về Twitter của bạn, có Twitter Gem sẽ giúp tự động hóa việc này cho bạn.

23

Restclient là giải pháp thực sự tốt cho vấn đề này.

require 'rest_client' 
RestClient.get 'http://example.com/resource' 
RestClient.get 'http://example.com/resource', {:params => {:id => 50, 'foo' => 'bar'}} 

Từ readme.

+1

Tôi mạnh mẽ đồng ý với RestClient. Nó thực sự là một khuôn khổ tuyệt vời để xử lý tất cả các cuộc gọi API. – mhenrixon

+0

Công cụ tuyệt vời. Đến từ iOS, đây chính xác là những gì tôi muốn. – samvermette

+1

Tôi rất thích RestClient thành HTTParty. Cảm thấy có căn cứ hơn, ít phép thuật hơn với tôi. YMMV – Duke

Các vấn đề liên quan