2009-04-14 19 views
54

Me gustaría escribir una aplicación Ruby on Rails que consuma una API de servicio web RESTful que realiza cierta lógica en el resultado y luego muestra esa información en mi vista. Por ejemplo, digamos que quería escribir un programa que realizó una búsqueda en search.twitter.com. El uso de rubí puro que podría crear el siguiente método:¿Cuál es el "modo Rails" adecuado para consumir un servicio web RESTful en otro dominio?

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 

estoy tentado a caer ese método en mi controlador de Rails como un método privado, pero una parte de mí piensa que hay una mejor, más "rieles" forma de hacer esto. ¿Hay un enfoque de mejores prácticas o esta es realmente la mejor manera?

Respuesta

51

Hay un complemento/gema llamado HTTParty que he usado para varios proyectos.

http://johnnunemaker.com/httparty/

HTTParty le permite consumir fácilmente cualquier servicio web y analiza los resultados en un hash para usted. Luego puede usar el hash mismo o crear una instancia de una o más instancias modelo con los resultados. Lo hice de las dos maneras.

Para el ejemplo gorjeo, el código se vería así:

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

Como último punto, se puede usar el código anterior también, pero definitivamente incluir el código en un modelo en lugar de un controlador.

+0

Me encanta esta joya. Esto hace que los servicios web que consumen sean realmente hábiles. Una pregunta que todavía tengo es si Rails ya tiene algo incorporado para hacer esto. Parece que esto es algo bastante común para tratar de hacer que tendrían una manera de hacerlo. –

+0

Además, perdone mi Rails noobieness :), ¿cómo podría configurar eso como modelo? Solo he usado modelos para acceder a bases de datos usando ActiveRecord. –

+7

No hay nada incorporado en el núcleo de los rieles. Un modelo es solo una clase: simplemente cree una clase en el directorio de modelos y no herede de la clase ActiveRecord: Base. No tendrá ninguna bondad de AR incluida, pero este es un patrón bastante común para consumir servicios web dentro de una aplicación de rieles. –

11

si el servicio web remoto RESTful también se creó con Ruby on Rails, ActiveResource es el camino a seguir.

+0

No puedo hacer esa suposición como me gustaría para extraer datos de muchos diferentes sitios web en la que yo no tendría ninguna idea de lo que sería el marco subyacente. Pero buscaré en ActiveResource las cosas que sé que son Rails. ¡Gracias! –

+4

En realidad, el servicio RESTful remoto no tiene que crearse utilizando Rails para que ActiveResource funcione. La implementación subyacente no importa. – WattsInABox

+0

Esta es definitivamente la forma preferida de Rails para consumir recursos RESTful. Mantiene el código limpio y se ajusta a MVC. –

2

En respuesta a su ejemplo de Twitter, hay un Twitter Gem que ayudaría a automatizar esto para usted.

23

Restclient es una muy buena solución a este problema.

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

A partir del readme.

+1

Estoy totalmente de acuerdo con RestClient. Es realmente un marco impresionante para manejar todas las llamadas API. – mhenrixon

+0

Excelentes cosas. Viniendo de iOS, esto es exactamente lo que quería. – samvermette

+1

Yo prefiero RestClient a HTTParty. Se siente más castigado, menos mágico para mí. YMMV – Duke

Cuestiones relacionadas