Ruby wrapper for Twitter Search API

Posted by Dan Croak

Sep 09

Twitter Search (formerly Summize) is sweet. I use it every day to find first-person commentary on thoughtbot’s work, Boston sports, national politics, and anything else that catches my fancy.

The Twitter Search API is also sweet. I wanted to use it a while back for Politweets. In combination with a simple cron job, the effect is commentary on the U.S. Presidential Election from around the world, seen within minutes of being tweeted.

Dustin Sallings wrote a great Ruby wrapper for the Summize API that he put on github. I forked it and added a shoulda test suite and documentation.

Introducing the Twitter Search gem.

Usage

Install the gem.

sudo gem install dancroak-twitter-search -s http://gems.github.com
Require the gem.

require 'twitter_search'
Set up a TwitterSearch::Client. Name your client (a.k.a. ‘user agent’) to something meaningful, such as your app’s name. This helps Twitter Search answer any questions about your use of the API.

@client = TwitterSearch::Client.new 'politweets'
Request tweets by calling the query method of your client.

@tweets = @client.query :q => 'twitter search'

Search Operators

The following operator examples find tweets…

Foreign Languages

The Twitter Search API supports foreign languages, accessible via the :lang key. Use the ISO 639-1 codes as the value:

@tweets = @client.query :q => 'programmé', :lang => 'fr'

Pagination

Alter the number of Tweets returned per page with the :rpp key. Stick with 10, 15, 20, 25, 30, or 50.

@tweets = @client.query :q => 'Boston Celtics', :rpp => '30'

Gotchas


@tweets = @client.query :q => 'Pearl Jam', :geocode => '43.4411,-70.9846mi'

Usage with ActiveRecord and cron

You can get fancier with your setup, using queuing or another approach, but here’s a simple example using cron.

Schema:
1
2
3
4
5
6
7
8
9
10
create_table "tweets", :force => true do |t|
  t.string   "user_name",          :limit => 20,  :default => "", :null => false
  t.string   "body",               :limit => 140, :default => "", :null => false
  t.datetime "created_at",                                        :null => false
  t.datetime "updated_at",                                        :null => false
  t.integer  "twitter_id",         :limit => 11
end

add_index "tweets", ["created_at"], :name => "index_tweets_on_created_at"
add_index "tweets", ["twitter_id"], :name => "index_tweets_on_twitter_id"
Hit the API in your rake task (write the code in a class so it can be easily tested):
1
2
3
4
5
class Twitter
  def self.import!
    # the implementation is up to you
  end
end
Since I don’t have the cron API memorized, I like to create cron jobs with a handy little tool called crondle:
1
2
3
4
5
6
7
8
9
require 'lib/crondle'

Crondle.define_jobs do |builder|
  rails_root = '/var/www/apps/politweets/current'
  [3, 9, 15, 21, 27, 33, 39, 45, 51, 57].each do |minute|
    builder.desc "Import tweets at #{minute} past the hour"
    builder.job "#{rails_root}/script/runner Twitter.import!", :minute => minute
  end
end
Run the crondle script to get the text that you’ll put in crontab -e:
1
2
3
4
5
6
7
# Import tweets at 3 past the hour
3 * * * * /var/www/apps/politweets/current/script/runner Twitter.import!

# Import tweets at 9 past the hour
9 * * * * /var/www/apps/politweets/current/script/runner Twitter.import!

...

And you’re on your way.

Thanks to Doug, Gabe, Jason, Min, and Dustin for their work on Politweets and the Twitter Search gem.


Comments on this post

Luke Francl

Sep 09

Luke Francl said,

Hm, interesting.

I used the Twitter Search API for Twistr but since it supports JSON it is like two lines of code to translate the results to Ruby.

But I think I will check this out next time I do a Twitter app.

John Nunemaker

Sep 09

John Nunemaker said,

Cool stuff. I love working with twitter’s apis. I added search support to my twitter gem a few weeks back but I took a bit different approach. The code for the search class is on github ( spec file ).

Basically, mine chains methods instead of using a hash.

1
2
search = Twitter::Search.new
search.from('jnunemaker').to('oaknd1').each { |r| puts r.inspect }
David Paquet

Sep 12

David Paquet said,

Hi !

We (me and a friend) are in the process of learning Rails. We already started developing an application but it was a bit too big for our first Rails project (we have a daytime job…)

But, when we saw your article, we knew we had to do the same thing for Canada since we are also having an election. With your post, we managed to do it in only one night and we learned alot in the process. Thanks !

David Paquet

Sep 13

David Paquet said,

Oops, forgot to mention the website yesterday : http://electopinion.ca

Korepetycje

Sep 13

Korepetycje said,

Thanks for sharing!

Dan Croak

Sep 16

Dan Croak said,

@John – I like your use of httparty. I’m going to have to mess with that.

@David – elect-o-pinion is awesome. Great job.

Keith Gautreaux

Sep 23

Keith Gautreaux said,

Dan, I’m new to Ruby and programming in general and I don’t have a github account that I can send a pull request from.

Long story short, shouldn’t the the Tweets class have an attr_reader :results declaration. This way you can use:

1
2
3

tweets_array = []
tweets_array = @tweets.results

Prior to making this change in my local gem I had to resort to:

1
2
3

tweets_array = []
tweets_array = @tweets.instance_variable_get(:@results).to_a

Please let me know if I’m confused, like I said, I’m a beginner.


Sorry, comments are closed for this article.

© 2000 - 2008 by thoughtbot, inc.
written by a bushel of tiny robots