Learn Why to Code

A brief introduction to practical programming

« Previous: Organizing your code environment Next: File existence and other considerations »

Writing More Wrappers

The problem: We're having trouble understanding the code we're reusing.
The solution: Wrap these routines in easy-to-read method calls.

Lesson content is currently in draft form.

Let’s build off of the my_code.rb file we made in the last chapter:

Our common code (my_code.rb) download
1
2
3
4
5
6
7
8
9
10
11
12
13
require 'rubygems'
require 'json'
require 'httparty'


###############
# Constants
TWITTER_DATA_HOST = "http://nottwitter.danwin.com"
TWITTER_USER_DATA_PATH = File.join(TWITTER_DATA_HOST, "users")
TWITTER_TWEETS_DATA_PATH = File.join(TWITTER_DATA_HOST, "statuses")


puts "Done loading my code!"

It’s been kind of annoying to re-formulate the URL for getting tweets and user info. So let’s use those constants to write methods to conveniently generate the needed URLs.

(this is just practice with no new concepts)

Exercise

Form the URL pattern for Twitter account info

Use the two constants we have in my_code.rb to build out a URL. You may want to use the File.join method

e.g. http://nottwitter.danwin.com/users/NancyPelosi/show.json

Call it: “

Form the URL pattern for a page of a user’s tweets

Same as above, except for a page of tweets

e.g. http://nottwitter.danwin.com/statuses/NancyPelosi/1/user_timeline.json

Call it: “

Downloading from a URL

This method downloads from a URL (yes, this may very well be a one-liner)

Getting a Twitter user account data as a Hash

Given an account name, this returns account data as a Hash

Getting a Twitter user’s page of tweets as an Array

Given an account name and page number, this returns tweet hashes as an Array.

Answer

Your my_code.rb should look like this:

Our common code redone (my_code.rb) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
require 'rubygems'
require 'json'
require 'httparty'


###############
# Constants
TWITTER_DATA_HOST = "http://nottwitter.danwin.com"
TWITTER_USER_DATA_PATH = File.join(TWITTER_DATA_HOST, "users")
TWITTER_TWEETS_DATA_PATH = File.join(TWITTER_DATA_HOST, "statuses")

def url_for_twitter_user_info(screen_name)
  # pre: screen_name a Twitter account name as a string
  # returns: url (string) to get user data

  File.join(TWITTER_USER_DATA_PATH, screen_name, 'show.json')
end

def url_for_tweets_page(screen_name, pg_num)
  # pre: screen_name is a Twitter account name, as a string; pg_num
  #      the page number, as tweets are separated into numbered pages


  # returns: url (string) to get tweets

  File.join(TWITTER_TWEETS_DATA_PATH, screen_name, pg_num.to_s, "user_timeline.json")
end

def get_data_file(u)
  # pre: u is a URL string
  # post: downloads from u; has no protection against bad URLs
  # i.e. this will have to be modified later

  HTTParty.get(u)

end

def get_twitter_user(screen_name)
  # pre: screen_name is a Twitter account name, as a string
  # returns: user info as a Hash object

  d = get_data_file( url_for_twitter_user_info(screen_name))
  JSON.parse(d)
end

def get_tweets_page(screen_name, pg_num)
  # pre: screen_name is a Twitter account name, as a string; pg_num
  #      the page number, as tweets are separated into numbered pages

  # returns: an array of tweet Hash objects

  d = get_data_file( url_for_tweets_page(screen_name, pg_num))
  JSON.parse(d)
end



puts "Done loading my code!"

The beauty of abstraction

What was the point of all that work? Was it needed?

We’re doing more and more complicated tasks. The details remain the same but the pure repetition of text makes it all seem like a jumble. Sometimes it’s worth it to stop trying new things and wrapping up what we’ve done in a nice package.

Revisit and refactor

Remember this exercise from a few chapters back?

File /Users/dairy/proj/octo-code6hrs/source/downloads/code/latest-tweets.rb could not be found

Write it out, but this time with our new methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
load './my_code.rb'

list_url = File.join(TWITTER_DATA_HOST, "simple-congress-list.txt")
str = get_data_file(list_url)
arr_of_names = str.split("\n")

arr_of_names.each do |name|
  tweets_arr = get_tweets_page(name, 1)     
  
  # just need the first tweet
  tweet = tweets_arr[0]
  puts name + " tweeted on " + tweet['created_at'] + ": " + tweet['text]    
end

Comments