In this multi-phase project, you will build a client that interacts with the Twitter messaging service. Your client will both mimic functionality found through the twitter.com web interface as well as perform many new tasks.
If you haven’t already setup Ruby, visit the environment setup page for instructions.
Before starting this tutorial, you should have a basic understanding of topics covered in Ruby in 100 Minutes, including:
- methods and arguments
- string interpolation
You should also be comfortable with:
- installing a gem
- using IRB
- writing methods
After completing this tutorial, you will be able to:
- require and reload files in irb
- understand the difference between
- get user input with
- use conditional branching and looping techniques with
- manipulate strings using methods like
- iterate through collections using
- check to see if an element is part of a collection using
- add elements to an existing array with the syntax
array << element
- select specific elements of array using the syntax
- set up and use an API (Application Programming Interface)
- implement functionality provided by various gems: klout, bitly, jumpstart_auth
What We’re Doing in This Tutorial
We’ll set up a Twitter client using the Jumpstart_Auth gem. Next, we’ll create a
tweet method to post a message to Twitter. We’ll implement functionality to allow
a command line user to specify whether to tweet, send a direct message, spam followers, see
everybody’s last tweet, or exit the program. Finally, we will use the Bitly gem
to shorten links and the Klout API to measure a user’s social network influence.
We won’t be creating a test suite with this project, but if you finish all
iterations, try writing tests as an extension.
The Twitter API and gem are constantly changing. We do our best to keep this tutorial updated, but sorry if things get confusing.
Iteration 0: Up & Running
Before building fancy features, let’s focus on getting something running.
jumpstart_auth gem by running this instruction from your command prompt (Windows) or terminal (OS X):
It’ll likely install several dependencies in addition to
Next, open your text editor. Create a file named
micro_blogger.rb and start it off with this structure:
1 2 3 4 5 6 7 8 9
Fire It Up
Let’s see if that little program is ready to run. From your terminal/command prompt, start "Interactive Ruby" with this instruction:
You’ll get a prompt that looks something like this:
At that prompt, load our microblogger.rb file and create a new instance of our MicroBlogger class by running these two instructions:
2.1.1 :001> 2.1.1 :002>
#<MicroBlogger:0x1014012b0> represents a MicroBlogger object.
Dealing with OAuth
When connecting to a third-party service (such as Twitter), from the developer’s perspective, possibly the simplest form of authentication is passing the user’s username and password. Unfortunately, this puts more work on the user and is not very secure or robust.
That’s where OAuth comes in. The OAuth authentication system is a more complex workflow that involves a lot of moving parts and can be confusing to understand at first.
Because of this, we’ve moved all of the complexity into the
so that we can focus on the important parts of this exercise. You can use this
jumpstart_auth library inside your initialize method like this:
1 2 3 4
Re-Run from IRB
Since we made a change to our file, we need to reprocess and load it back into irb. Run this command from Terminal:
2.1.1 :001> 2.1.1 :002>
The first time this is run it’ll use the
Launchy gem to pop open your web
browser and ask for permission to use your account. We strongly recommend
that you use one of our demo accounts (if you’re in a class) or a fake account
you setup yourself.
Twitter will then give you a pin number that’s about 10 digits. Copy it to your
clipboard, go over to your IRB session, and paste it in where the prompt says
Enter the supplied pin:.
After entering the pin, we’ll have a
@client variable which holds our
connection to Twitter. With that setup, we can move forward.
Iteration 1: Posting Tweets
Now that we have the
@client object, we need to know what methods are
available from the Twitter library. In other words, what Ruby code can we write
that will interact with Twitter’s API.
The best information is available on the project readme file here.
In the readme you’ll find a section "Usage Examples" which clues you into some
of the functions exposed by the library. One of the methods we have access to is
update, which allows us to post to the Twitter account we’re using.
Step 1 - Write the
Now add the the following method to your class:
1 2 3
Then at the very end of the file, add these lines as an execution script:
Then run your code by going to your terminal an entering:
You should see the output say
Initializing. Now go to your test account’s Twitter page and look for your results!
Step 2 - Length Restrictions
Twitter messages are limited to 140 characters. Experiment with your current
program and see what happens if your try to call
tweet with a message longer
than 140. Did all of the message post? Part of it? Any of it? Let’s create some
error checking that will prevent the user from posting messages longer than 140.
Here’s some pseudocode for what we want our
tweet method to do:
- If the message to tweet is less than or equal to 140 characters long, tweet it.
- Otherwise, print out a warning message and do not post the tweet.
Inside of your
tweet method, write the code that will perform this logic.Test
tweet method with a message that is less than 140 characters, one
that is exactly 140 characters, and one that’s longer than 140 characters.
Wondering how to get a string that’s exactly 140 characters? Here’s how I did it:
Iteration 2: A Better Interface
Our client is off to a good start, but the interface sucks. We have to change lines in the Ruby file for each tweet we want to send – that’s not reasonable! Let’s write code that will allow a user to control the program from the command line.
Let’s build an interactive prompt interface to run our program.
Step 0 - Outline the Process
First, let’s define a method named
run which will be the instruction that gets
repeated over and over:
1 2 3
Then go to the last line of your program and change it to
Run your program at the command line with
ruby micro_blogger.rb and you should just see the line "Welcome to the JSL Twitter Client!"
Step 1 - The Loop
puts "Welcome to the JSL Twitter Client!" line we’ll use a
while loop to repeat instructions over and over. Add these lines below the
puts but before the
1 2 3 4
Remember that you can exit a running Ruby application by pressing Control-C if you just so happen to get in an infinite loop.
Go ahead and run that program and you should see the "enter command: " string over and over. Why?
while loop will keep repeating until the variable
command contains the value
"q". Since we set
command to the empty string and aren’t changing it, the loop continues forever.
Also, you might wonder what
printf is about. Why not
puts? The difference is that
printf prints text and leaves the cursor there, while
puts prints text then starts a new line. For our interface, we’ll have the prompt and the command on the same line.
Step 2 - Accepting Input
In Ruby we can accept user string with the
gets command. Add this line below your
Now run your program again and it’ll wait for you to enter commands. Try typing some things in. Try entering a
q to quit.
It doesn’t work, right? There’s a little gotcha with using
gets – it picks up the enter key too. So your
command variable is actually getting the string
"q\n" where that backslash-n is a new line. The fix is to change
chomp method will remove any whitespace (spaces, tabs, newlines) on the back end of a string.
After you add the
chomp try your program again and you should be able to quit with just
Step 3 - Starting a Case Statement
We think we’re getting the instruction from the user, but we need to actually do something with it. We’ll use what’s called a case statement. Case statements in Ruby look like this:
1 2 3 4 5 6 7
Ruby will look at the variable
input and see what value it holds. If the value matches one of the
when lines, then it’ll do the instruction(s) that follow that line’s
then. If it doesn’t match any of the
when lines, it’ll run the
Start with this case statement in your method just below the
command = gets.chomp line:
1 2 3 4 5
Run your program and test some commands.
Step 4 - Tweeting & Parameters
Let’s make this thing work for our tweet method. Add a
when line that is run when the
"t". Have it call our
Run your program and try entering
t This is only a test!.
You should see output like
Sorry, I don't know how to (t This is only a test!).
I wanted it to call the
tweet method because I started the line with
but then the rest of the line was my message. Instead, it thought the whole line
was the command. We need to divide up the input between the command and the text
that should be sent to that command.
There are a few ways we could accomplish this, but we’ll use the most straightforward method.
Making the Command-Line Interface Smarter
We want the
command variable to be just the first letter(s) that are entered.
But right now, the line
command = gets.chomp isn’t just getting the
it’s getting a
command and a message to send to that command. Let’s change this
input = gets.chomp then we’ll work with
input to pull out the command.
Now that we have
input we need to split it up into pieces. We’ll cut it up
split method. Just below the
input = gets.chomp add a line that
parts = input.split(" ") to cut
input into an array of
split will take our input string (entered by the user at the
command line) and chop it into an array of smaller strings. Whatever argument we
.split will be where the string gets chopped.
For example, if the user gave the input:
t tweet my message
input = gets.chomp would produce a
parts array that looked like this:
["t", "tweet", "my", "message"]
Knowing the structure of this array will allow us to pull out the
parts we need at various places in our program. In the example
parts array above,
t is the command we’re looking for, so let’s pull it out by saying
command = parts.
The rest of the elements in
parts are our message. We can change these parts
back into a string with
parts[1..-1].join(" "). This means: take all the parts
from index 1 to the end of the array (-1) and put them together with a space between
Using that idea in the
when line for
t, here’s what my
run method looks like right now:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Try it out and you should finally be able to post tweets over and over!
Iteration 3: Send Direct Messages
Sending Direct Messages isn’t that different from posting a tweet. In fact, we
can reuse our existing
tweet method to do all the hard work.
Step 0 - Frameworks
dm method will take a target (Twitter handle for some user) and a message:
1 2 3 4
And we need to add the command to our
run method. We’ll enter the instruction
dm jumpstartlab Here is the text of the DM, so our
when line should
look like this:
parts is the command itself, here
be the target username, here
jumpstartlab. Then everything else is the message,
so we join them with spaces
Step 1 - Create and Send the Message
First, let’s add to our
dm method. We’ll create a variable
message which will
be a combination of the letter d, a target, and a message.
1 2 3 4 5 6
Then call the
tweet method with this new string as the parameter message.
Log into your personal Twitter account and follow the fake account you created. (You will need to do this before you can send a direct message.) Then try sending yourself a direct message from your MicroBlogger.
Step 2 - Error Checking DM-ability
You can only DM people who are following you. If you try and DM someone who doesn’t follow you, it doesn’t give you an error message. It just fails silently.
Let’s add a way to verify that the target is following you before sending the message. In pseudo-code, it’d go something like this:
- Find the list of my followers
- If the target is in this list, send the DM
- Otherwise, print an error message
We can call
@client.followers which gives us back a list of all our followers
but includes lots of information we don’t need right now like their follower count,
web address, last tweet. All we want is to find their
What we need to do is pull out just the
screen_name. We create an array of the
followers’ screen names with this line of code:
To read this line out loud it would be like "Call the
followers method of
@client, then take that array and, for each element in the array,
together the value of
Now you have an array of your followers’ screen names. Create a conditional block that follows this logic:
- If the
targetusername is in the
screen_nameslist (use Array#include? method), then send the DM
- Otherwise, print out an error saying that you can only DM people who follow you
Test your code by sending a DM to someone who does follow your demo account and someone who does not.
Step 3 - Spamming Your Friends
It would be cool to be able to send the same message out to all of our followers. We’ll accomplish this in two parts:
- Create a method named
followers_listthat returns an array containing the usernames of all my followers
- Create a method named
spam_my_followersthat finds all followers from
followers_listand tries to send them a Direct Message using the
To create the
- Define the method named
followers_listwith no parameters
- Create a blank array named
- On the
followersmethod iterate through
eachof them performing the instruction below:
- Return the array
Then for the
- Define the method named
spam_my_followerswith a parameter named
- Get the list of your followers from the
- Iterate through
eachof those followers and use your
dmmethod to send them the
Then create a
when line in your
run method for the command
spam. It will look just like the
tweet line, except it’ll send the message into the
Test it out and see how many followers you can annoy at once!
Iteration 4: Last Tweet from All Friends
So now you can post tweets and DMs. There are hundreds of clients that can do that. If you’re a normal twitter user you follow some people who post several times per day and some people who post once per week. It can be difficult to see everyone. Lets create a list of the last tweet for each person you follow.
Step 0 - Framework
Here it is in pseudocode:
Find the list of people you follow
eachmember of the list…
- Find their latest tweet
- Print out their
screen_nameand latest tweet
Turn that into code like this…
1 2 3 4 5 6 7 8 9
when line to your
run method for this instruction. I’m using the instruction
elt so my
when line is just
when 'elt' then everyones_last_tweet. Once added, restart your program and try it out.
Step 1: Finding the Last Messages
When you call the
friends method you get an array list where each element of the array is an object representing one friend. The object has all the information about an individual friend such as
followers_count, etc. Here are the useful properties that it has:
So for each of those
friend objects, if you call
friend.followers_count you’ll get their number of followers. Or use
friend.id to get their unique Twitter ID number.
status contains their last tweet, but there’s a catch –
status is ANOTHER complex object, not simply a string. The
status object has these properties and methods:
So if you want to access one of these pieces of data you’d call it like this:
Now that you understand the hashes available to you, implement code for the three commented lines in our
everyones_last_tweet method. RUN your program and you should see output kinda like this:
Step 2: Improving the Output
Getting each friend’s last message was cool, but they’re in some random order. Sort them by the
screen_name in alphabetical order! I want you to hack out the code, but the way I did it would read like this:
"take the friends list and use the Array#sort_by method, then call each one
friend and find the
friend.screen_name". You might look at how you used
sort_by in EventManager for syntax clues. (NOTE: Ruby considers all capital letters to come earlier in alphabetical order than lowercase letters. To keep all your letters together regardless of capitalization, change
friend.screen_name.downcase when sorting)
Second, these messages are lacking any time context. The
status hash has a key named
created_at which holds a string like this one:
Thu Jul 23 23:31:16 +0000 2009. That’s the information we need, but it’s in an ugly format. Use these steps to make the data more useable:
1 2 3 4
is my most hated method in Ruby because every time I use it I need to
lookup the dumb parameters. The
"%A, %b %d" that I gave you will cause it to
output the date formatted like
Wednesday, Jul 29. Implement the sorting and
the timestamping to create output that looks like this:
Iteration 5: Shorten URLs with Bit.ly
There’s a great library which can be used to automatically create shortened URLs. Let’s add this functionality into our project.
Step 0 - Testing the Library
First, go into Terminal and run this line:
irb and try out the following:
1 2 3 4 5 6
It might take a few seconds, but you should now have a shortened URL from Bitly’s shortner service. Try it out in your browser to make sure it works.
Step 1 - Framework
Create this method:
1 2 3 4
when line to your
run method so that the command
s will take one parameter and send it into the
Step 2 - Implement the Method
Look at the model for Bitly that we used in Step 0 and use it to fill in the shortening code of your
shorten method. Make sure that your method ends with a
return statement so it sends the shortened URL that to the method that called it.
Step 3 - Tweet with URL
How can we shorten a url while posting a tweet? There are a few ways to do it. Here’s an easy one:
when line in your
run method for the command
turl which stands for "Tweet with URL". Make it accept commands that look like this:
turl I wrote this twitter client at: http://jumpstartlab.com
You know that
parts is the command,
parts[1..-2] are the message, and
parts[-1] is the URL to be shortened. You can put that all together like this:
tweet(parts[1..-2].join(" ") + " " + shorten(parts[-1]))
Get that working and you’re done with the twitter client!
Iteration 6: The Klout API
Let’s continue experimenting with various APIs.
Klout (klout.com) is a service that, "measures influence on social networks." The Klout service analyzes a variety of networks to determine an individual’s "Klout Score." Measured from 0 to 100, a higher Klout Score indicates greater influence on various social networks.
Klout offers a free public API that lets you retrieve Klout scores by simply providing a Twitter username. Let’s attempt to retrieve the Klout Score of all the users you follow and see who has the greatest influence!
Step 0 - Testing the API
First, hop into Terminal and run this line:
irb so you can experiment with the Klout API. Run the following lines:
2.1.1 :001> 2.1.1 :002> 2.1.1 :003> 2.1.1 :004> 2.1.1 :005>
While the format of the second command may be a bit confusing, you’re simply asking Klout to return a user’s Klout Score in a format you can read and interpret. In this example, you’ve provided the Twitter username
jack (the original creator of Twitter), and Klout returned the value
74.61. You can easily change out
jack for any other Twitter username, so let’s obtain the Klout Score for everyone you follow!
Step 1 - Require Klout
First, you’ll want to require the Klout gem in your MicroBlogger implementation, and make sure you can make requests to the Klout service. At the top of your
micro_blogger.rb file, insert the following just below require
Next, in your initialize method, insert the following:
Great! Now you’re set up to make requests to Klout’s API!
Step 2 - Obtain Klout Scores
You’ve already written logic to obtain a list of your friends, which looks something like this:
If you wanted to write a method that prints out the Klout score for all of your friends, its logic would be structured something like this:
- Obtain a list of all your friends, and save that list inside a variable named
screen_names(this is done using the method above).
- Step through the list of friends. For each
friend, issue a request to Klout to obtain their Klout score.
- Print out each
screen_namefollowed by their Klout score.
Here’s the basic setup for this method, you can fill in the gaps:
1 2 3 4 5 6 7 8
Once you’re finished, test the method by inserting the following line at the bottom of the
and then run the program. Who has the highest Klout score amongst your friends?