I would like to write a Ruby on Rails application that consumes a RESTful web service API performs some logic on the result and then displays that data on my view. For example, let's say I wanted to write a program that did a search on search.twitter.com. Using pure ruby I might create the following method:
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
I'm tempted to just drop that method into my Rails controller as a private method, but part of me thinks that there is a better, more "Rails" way to do this. Is there a best practice approach or is this really the best way?
-
Hi Mike, if the remote RESTful web service was also created with Ruby on Rails, ActiveResource is the way to go.
Mike Farmer : I can't make that assumption as I would like to pull data from many different web sites wherein I would have no idea what the underlying framework would be. But I'll look at ActiveResource for the things I know are Rails. Thanks! -
In response to your Twitter example, there is a Twitter Gem that would help to automate this for you.
-
There is a plugin/gem called HTTParty that I've used for several projects.
http://httparty.rubyforge.org/
HTTParty lets you easily consume any web service and parses results into a hash for you. Then you can use the hash itself or instantiate one or more model instances with the results. I've done it both ways.
For the twitter example, your code would look like this:
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')
As a last point, you could use your code above also, but definitely include the code in a model as opposed to a controller.
Mike Farmer : I love this gem. This makes consuming web services really slick. A question I still have though is whether Rails has something built in already to do this? Seems like this is a common enough thing to try to do that they would have a way to do it.Mike Farmer : Also, forgive my Rails noobieness :) , how would I set that up in as a model. I have only used models for database access using ActiveRecord.Kyle Boon : There isn't anything built in to rails core. A model is a just a class - just create a class in the models directory and don't inherit from the ActiveRecord:Base class. You won't have any of the AR goodness included, but this is a pretty common pattern for consuming web services within a rails appMike Farmer : Thanks! I'll give it a try. I appreciate the help.Angela : Mike, did you settle on HttpParty and are you using it to do POST's to non-rest HTTP web services? I am using rest-client, not sure if it's working right though so wanted you take?
0 comments:
Post a Comment