Swine Flu and the Twitter Gem »
Created at: 19.05.2009 01:11, source: RailsTips - Home, tagged: gems httparty twitter
In which I wax poetic about the trendy new addition to the Twitter gem.
I had some extra time today and I’ve been spotty on open source work over the past few weeks, so I decided to add support for the Twitter trends API to my Twitter gem.
Using HTTParty, the code for this turned out to be insanely simple, so short, in fact, that I’ll just put it inline here so you don’t even have to go over to Github. Aww, I’m so nice.
module Twitter
class Trends
include HTTParty
base_uri 'search.twitter.com/trends'
format :json
# :exclude => 'hashtags' to exclude hashtags
def self.current(options={})
mashup(get('/current.json', :query => options))
end
# :exclude => 'hashtags' to exclude hashtags
# :date => yyyy-mm-dd for specific date
def self.daily(options={})
mashup(get('/daily.json', :query => options))
end
# :exclude => 'hashtags' to exclude hashtags
# :date => yyyy-mm-dd for specific date
def self.weekly(options={})
mashup(get('/weekly.json', :query => options))
end
private
def self.mashup(response)
response['trends'].values.flatten.map { |t| Mash.new(t) }
end
end
end
Pure TDD
I am most definitely a tester, but I’ll admit I usually write code and then write the test. Of late, I’ve been reversing this trend and actually practicing TDD in full force by writing a small test, then only enough code to make it pass, followed by another test or more code for the existing test, finished with just enough code to make the new addition pass.
It is a different mindset to code in this way, compared to my code first and then make sure my butt is covered method and I’ve loving it. I thought I would find pure TDD tedious, but on the contrary, I think I’m coding faster and cleaner.
The Tests
So how did I test the code above? Again, inline for your viewing pleasure, are the tests I added to make sure I don’t break something in the future and get yelled at. Feel free to take a gander and I’ll meet back up with you at the bottom of it.
require File.dirname(__FILE__) + '/../test_helper'
class TrendsTest < Test::Unit::TestCase
include Twitter
context "Getting current trends" do
should "work" do
stub_get('http://search.twitter.com:80/trends/current.json', 'trends_current.json')
trends = Trends.current
trends.size.should == 10
trends[0].name.should == '#musicmonday'
trends[0].query.should == '#musicmonday'
trends[1].name.should == '#newdivide'
trends[1].query.should == '#newdivide'
end
should "be able to exclude hashtags" do
stub_get('http://search.twitter.com:80/trends/current.json?exclude=hashtags', 'trends_current_exclude.json')
trends = Trends.current(:exclude => 'hashtags')
trends.size.should == 10
trends[0].name.should == 'New Divide'
trends[0].query.should == %Q(\"New Divide\")
trends[1].name.should == 'Star Trek'
trends[1].query.should == %Q(\"Star Trek\")
end
end
context "Getting daily trends" do
should "work" do
stub_get('http://search.twitter.com:80/trends/daily.json?', 'trends_daily.json')
trends = Trends.daily
trends.size.should == 480
trends[0].name.should == '#3turnoffwords'
trends[0].query.should == '#3turnoffwords'
end
should "be able to exclude hastags" do
stub_get('http://search.twitter.com:80/trends/daily.json?exclude=hashtags', 'trends_daily_exclude.json')
trends = Trends.daily(:exclude => 'hashtags')
trends.size.should == 480
trends[0].name.should == 'Star Trek'
trends[0].query.should == %Q(\"Star Trek\")
end
should "be able to get for specific date (with date string)" do
stub_get 'http://search.twitter.com:80/trends/daily.json?date=2009-05-01', 'trends_daily_date.json'
trends = Trends.daily(:date => '2009-05-01')
trends.size.should == 440
trends[0].name.should == 'Swine Flu'
trends[0].query.should == %Q(\"Swine Flu\")
end
should "be able to get for specific date (with date object)" do
stub_get 'http://search.twitter.com:80/trends/daily.json?date=2009-05-01', 'trends_daily_date.json'
trends = Trends.daily(:date => Date.new(2009, 5, 1))
trends.size.should == 440
trends[0].name.should == 'Swine Flu'
trends[0].query.should == %Q(\"Swine Flu\")
end
end
context "Getting weekly trends" do
should "work" do
stub_get('http://search.twitter.com:80/trends/weekly.json?', 'trends_weekly.json')
trends = Trends.weekly
trends.size.should == 210
trends[0].name.should == 'Happy Mothers Day'
trends[0].query.should == %Q(\"Happy Mothers Day\" OR \"Mothers Day\")
end
should "be able to exclude hastags" do
stub_get('http://search.twitter.com:80/trends/weekly.json?exclude=hashtags', 'trends_weekly_exclude.json')
trends = Trends.weekly(:exclude => 'hashtags')
trends.size.should == 210
trends[0].name.should == 'Happy Mothers Day'
trends[0].query.should == %Q(\"Happy Mothers Day\" OR \"Mothers Day\")
end
should "be able to get for specific date (with date string)" do
stub_get 'http://search.twitter.com:80/trends/weekly.json?date=2009-05-01', 'trends_weekly_date.json'
trends = Trends.weekly(:date => '2009-05-01')
trends.size.should == 210
trends[0].name.should == 'TGIF'
trends[0].query.should == 'TGIF'
end
should "be able to get for specific date (with date object)" do
stub_get 'http://search.twitter.com:80/trends/weekly.json?date=2009-05-01', 'trends_weekly_date.json'
trends = Trends.weekly(:date => Date.new(2009, 5, 1))
trends.size.should == 210
trends[0].name.should == 'TGIF'
trends[0].query.should == 'TGIF'
end
end
end
So, yeah, nothing earth shattering. It feels a bit repetitive, but I don’t mind some amount of repetition in my tests. The fixture files were created quite simply using curl.
cd test/fixtures
curl http://search.twitter.com:80/trends/weekly.json?date=2009-05-01 > trends_weekly_date.json
# rinse and repeat for each file
The stub_get method is a simple wrapper around FakeWeb and looks something like this:
def stub_get(url, filename, status=nil)
options = {:string => fixture_file(filename)}
options.merge!({:status => status}) unless status.nil?
FakeWeb.register_uri(:get, url, options)
end
def fixture_file(filename)
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
File.read(file_path)
end
I’m lazy and find that stub_get is much shorter than FakeWeb.register_uri blah, blah, blah. The tests use FakeWeb, shoulda and my fork of matchy, in case you are curious.
Example Uses
So what can you do with the new trends addition? Below are some examples of how you can obtain trend information.
Twitter::Trends.current
Twitter::Trends.current(:exclude => 'hashtags')
Twitter::Trends.daily # current day
Twitter::Trends.daily(:exclude => 'hashtags')
Twitter::Trends.daily(:date => Date.new(2009, 5, 1))
Twitter::Trends.weekly # current day
Twitter::Trends.weekly(:exclude => 'hashtags')
Twitter::Trends.weekly(:date => Date.new(2009, 5, 1))
That’s all for now. Enjoy the new trends and build something cool. Oh, and if you want to play with trends, but don’t have an idea, I have one and most likely won’t have time to build it. I’d be happy to collaborate.
more »
Question: Plugins or Gems? (or both?) »
Created at: 13.01.2009 21:56, source: Robby on Rails, tagged: Ruby on Rails ruby programming question rubyonrails rails gems plugins
Our development team likes to extract reusable pieces of code for our projects and have historically used plugins. However, we are finding more and more people releasing these sorts of modules/components/patterns as gems.
Which do you prefer and why?
If you use both, how do you decide to use plugins or gems?
more »
