Escolar Documentos
Profissional Documentos
Cultura Documentos
TWO THINGS TO
KNOW ABOUT ME
I created the Ruby Quiz and ran it for the first three years
HI. I’M JAMES AND
I READ CODE.
HOW MUCH SHOULD
YOU READ?
0% 25% 50% 75%
100%
Novice
Advanced Beginner
Competent
Proficient
Expert
json = twitter["friends_timeline.json"].get
tweets = JSON.parse(json)
tweets.each do |tweet|
# ...
end
BASIC GET
Reading tweets with Twitter’s API
require "rubygems"
require "rest_client"
require "json"
BASIC POST
Posting a tweet with Twitter’s API
NETWORKING CODE
DONE RIGHT
def process_result(res)
if res.code =~ /\A2\d{2}\z/
decode res['content-encoding'], res.body if res.body
elsif %w(301 302 303).include? res.code
url = res.header['Location']
def transmit(uri, req, payload)
setup_credentials(req) if url !~ /^http/
uri = URI.parse(@url)
net = net_http_class.new(uri.host, uri.port) uri.path = "/#{url}".squeeze('/')
net.use_ssl = uri.is_a?(URI::HTTPS) url = uri.to_s
net.verify_mode = OpenSSL::SSL::VERIFY_NONE end
net.read_timeout = @timeout if @timeout
net.open_timeout = @open_timeout if @open_timeout raise Redirect, url
elsif res.code == "304"
display_log request_log raise NotModified, res
elsif res.code == "401"
net.start do |http| raise Unauthorized, res
res = http.request(req, payload) elsif res.code == "404"
display_log response_log(res) raise ResourceNotFound, res
string = process_result(res) else
raise RequestFailed, res
if string or @method == :head end
Response.new(string, res) end
else
nil
end
end
rescue EOFError
raise RestClient::ServerBrokeConnection def decode(content_encoding, body)
rescue Timeout::Error if content_encoding == 'gzip' and not body.empty?
raise RestClient::RequestTimeout Zlib::GzipReader.new(StringIO.new(body)).read
end elsif content_encoding == 'deflate'
Zlib::Inflate.new.inflate(body)
else
body
end
end
A RESTFUL SHELL
(IN 90 LOC)
$ restclient \
> get http://twitter.com/statuses/friends_timeline.json?count=1 \
> JEG2 secret
[{"text":"Sent out first round of Twitter client betas…",
"user":{"name":"Jeremy McAnally","screen_name":"jeremymcanally",…},
…}]
CURL-ISH REQUESTS
Fetching the latest tweet !om Twitter’s API
$ restclient http://twitter.com/statuses JEG2 secret
>> post "update.json", :status => "The RestClient shell is fun."
=> "{\"text\":\"The RestClient shell is fun.\",…}"
>> get "friends_timeline.json?count=1"
=> "[{\"text\":\"The RestClient shell is fun.\",…}]"
RESTFUL IRB
Interacting with the Twitter API
LOGGING IN RUBY
$ RESTCLIENT_LOG=twitter_fun.rb restclient …
>> post "update.json", :status => "The RestClient shell is fun."
=> …
>> get "friends_timeline.json?count=1"
=> …
# twitter_fun.rb
RestClient.post "http://twitter.com/statuses/update.json",
"status=The%20RestClient%20shell%20is%20fun.",
:content_type=>"application/x-www-form-urlencoded"
# => 200 OK | application/json 379 bytes
RestClient.get "http://twitter.com/statuses/friends_timeline.json?count=1"
# => 200 OK | application/json 381 bytes
GENERATING RUBY
Interactively building a RESTful Ruby script
FASTERCSV IS
THE NEW CSV
THE LESS BORING
PARTS OF CSV
Tricky data structures are needed
data = <<END_DATA
Console,Units Sold 2007,Percent,Units Sold 2008,Percent
Wii,"719,141",49.4%,"1,184,651",49.6%
XBox 360,"333,084",22.9%,"743,976",31.1%
PlayStation 3,"404,900",27.8%,"459,777",19.3%
END_DATA
ps3 = CSV.parse(data, :headers => true, :header_converters => :symbol)[-1]
CSV::ROW
The various ways to refer to data
M17N IN ACTION
@io = if data.is_a? String then StringIO.new(data) else data end
@encoding = if @io.respond_to? :internal_encoding
@io.internal_encoding || @io.external_encoding
elsif @io.is_a? StringIO
@io.string.encoding
end
@encoding ||= Encoding.default_internal || Encoding.default_external
def encode_re(*chunks)
Regexp.new(encode_str(*chunks))
end
def encode_str(*chunks)
chunks.map { |chunk| chunk.encode(@encoding.name) }.join
end
sample = read_to_char(1024)
sample += read_to_char(1) if sample[-1..-1] == encode_str("\r") and
not @io.eof?
if sample =~ encode_re("\r\n?|\n")
@row_sep = $&
break
end
OTHER POINTS
OF INTEREST
The parser
Using pipes
Signal handling
begin
block.call
ensure
Signal.trap(signal, handler)
end
end
def plot_to_kill pid, options = {}
seconds = getopt :in, options
signal = getopt :with, options
process.puts [pid, seconds, signal].join(' ')
process.flush
end
fattr :process do
process = IO.popen "#{ ruby } #{ program.inspect }", 'w+'
at_exit do
begin
Process.kill -9, process.pid
rescue Object
end
end
process.sync = true
process
end
fattr :program do
code = <<-code
while(( line = STDIN.gets ))
pid, seconds, signal, *ignored = line.strip.split
pid = Float(pid).to_i
seconds = Float(seconds)
signal = Float(signal).to_i rescue String(signal)
sleep seconds
begin
Process.kill signal, pid
rescue Object
end
end
code
tmp = Tempfile.new "#{ ppid }-#{ pid }-#{ rand }"
tmp.write code
tmp.close
tmp.path
end
OTHER POINTS
OF INTEREST
bj – A robust background priority queue for Rails
Have a goal
GETTING THE CODE
irb -r a_class_to_play_with