#!/usr/bin/env ruby
# vim: et ts=2 sw=2

require "sinatra"
require "octokit"
require "redis"
require "json"

# Init

$redis = Redis.new
VERSION = %x{git show-ref --hash=7 --head HEAD}.strip
NAMESPACE = "pullstatus:#{VERSION}"
TTL = 60 * 5



# Routes

get "/:user/:repo/pull/:num" do
  pull_request = PullRequest.new params
  send_file "images/#{pull_request.status}.png",
    :last_modified=>pull_request.updated_at
end


# Models

class PullRequest
  def initialize params
    @user = params[:user]
    @repo = params[:repo]
    @num = params[:num]
  end

  def status
    if pull_request["merged_at"]
      "merged"

    elsif pull_request["closed_at"]
      "rejected"

    else
      "open"
    end
  end

  def method_missing meth, *args, &block
    pull_request[meth.to_s]
  end

  def pull_request
    @pr ||= get!
  end

  private

  def key
    "#{NAMESPACE}:#{repo}/#{@num}"
  end

  def repo
    "#{@user}/#{@repo}"
  end

  def get!
    json = $redis.get(key)

    if json.nil?
      json = fetch!.to_json
      $redis.setex key, TTL, json
    end

    JSON.parse(json)
  end

  def fetch!
    puts "Fetching: #{key} PUTS"
    Octokit.pull(repo, @num)
  end
end

#!/usr/bin/env ruby
# vim: et ts=2 sw=2

require "sinatra"
require "octokit"
require "redis"


# Init

redis = Redis.new
NS = "pullstate"
TTL = 60 * 5


# Routes

get "/:user/:repo/pull/:number" do
  k = key params
  fn = redis.get k

  unless fn
    fn = state params
    redis.setex k, TTL, fn
  end

  send_file "images/#{fn}.png"
end


# Helpers

def key p
  "#{NS}:#{p[:user]}/#{p[:repo]}/#{p[:number]}"
end

def pull_request! p
  repo = "#{p[:user]}/#{p[:repo]}"
  Octokit.pull repo, p[:number]
end

def state p
  pull = pull_request! p
  if pull.merged_at
    "merged"

  elsif pull.closed_at
    "rejected"

  else
    "open"
  end
end
--- 
+++ 
@@ -4,50 +4,78 @@
 require "sinatra"
 require "octokit"
 require "redis"
-
+require "json"
 
 # Init
 
-redis = Redis.new
-NS = "pullstate"
+$redis = Redis.new
+VERSION = %x{git show-ref --hash=7 --head HEAD}.strip
+NAMESPACE = "pullstatus:#{VERSION}"
 TTL = 60 * 5
+
 
 
 # Routes
 
-get "/:user/:repo/pull/:number" do
-  k = key params
-  fn = redis.get k
-
-  unless fn
-    fn = state params
-    redis.setex k, TTL, fn
-  end
-
-  send_file "images/#{fn}.png"
+get "/:user/:repo/pull/:num" do
+  pull_request = PullRequest.new params
+  send_file "images/#{pull_request.status}.png",
+    :last_modified=>pull_request.updated_at
 end
 
 
-# Helpers
+# Models
 
-def key p
-  "#{NS}:#{p[:user]}/#{p[:repo]}/#{p[:number]}"
-end
+class PullRequest
+  def initialize params
+    @user = params[:user]
+    @repo = params[:repo]
+    @num = params[:num]
+  end
 
-def pull_request! p
-  repo = "#{p[:user]}/#{p[:repo]}"
-  Octokit.pull repo, p[:number]
-end
+  def status
+    if pull_request["merged_at"]
+      "merged"
 
-def state p
-  pull = pull_request! p
-  if pull.merged_at
-    "merged"
+    elsif pull_request["closed_at"]
+      "rejected"
 
-  elsif pull.closed_at
-    "rejected"
+    else
+      "open"
+    end
+  end
 
-  else
-    "open"
+  def method_missing meth, *args, &block
+    pull_request[meth.to_s]
+  end
+
+  def pull_request
+    @pr ||= get!
+  end
+
+  private
+
+  def key
+    "#{NAMESPACE}:#{repo}/#{@num}"
+  end
+
+  def repo
+    "#{@user}/#{@repo}"
+  end
+
+  def get!
+    json = $redis.get(key)
+
+    if json.nil?
+      json = fetch!.to_json
+      $redis.setex key, TTL, json
+    end
+
+    JSON.parse(json)
+  end
+
+  def fetch!
+    puts "Fetching: #{key} PUTS"
+    Octokit.pull(repo, @num)
   end
 end
Add last-modified header to response.

This involved a pretty big refactoring of the app. Previously, we were
only storing (in redis) the calculated state of each pull request. Now
we're storing the entire response.
