82
And the Greatest of These Is... Rack Support Ben Scofield Viget Labs Saturday, July 25, 2009

And the Greatest of These Is ... Space

Embed Size (px)

DESCRIPTION

Presentation given at Rails Underground; revision of earlier version given at Railsconf 2009.

Citation preview

Page 1: And the Greatest of These Is ... Space

And the Greatest of These Is... Rack SupportBen Scofield – Viget Labs

Saturday, July 25, 2009

Page 2: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 3: And the Greatest of These Is ... Space

Application TemplatesSaturday, July 25, 2009

Page 4: And the Greatest of These Is ... Space

Nested Attribute Assignmentflickr: angelrays

Saturday, July 25, 2009

Page 5: And the Greatest of These Is ... Space

ActiveRecord::Base#touchflickr: jjjohn

Saturday, July 25, 2009

Page 6: And the Greatest of These Is ... Space

DB Seedingflickr: richardthomas78

Saturday, July 25, 2009

Page 7: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 8: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 9: And the Greatest of These Is ... Space

Rack

Saturday, July 25, 2009

Page 10: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 11: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 12: And the Greatest of These Is ... Space

def call(env) [ status, # 200 headers, # {"Content-Type" => "text/html"} body # ["<html>...</html>"] ]end

Saturday, July 25, 2009

Page 13: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 14: And the Greatest of These Is ... Space

requestapplication

responseSaturday, July 25, 2009

Page 15: And the Greatest of These Is ... Space

requestapplication

response

middleware

middleware

Saturday, July 25, 2009

Page 16: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 17: And the Greatest of These Is ... Space

Rack::Profilerflickr: oberazzi

Saturday, July 25, 2009

Page 18: And the Greatest of These Is ... Space

Rack::MailExceptionsflickr: warmnfuzzy

Saturday, July 25, 2009

Page 19: And the Greatest of These Is ... Space

Rack::Cacheflickr: timpatterson

Saturday, July 25, 2009

Page 20: And the Greatest of These Is ... Space

rack::cascade

Rack::Cascadeflickr: _at

Saturday, July 25, 2009

Page 21: And the Greatest of These Is ... Space

Rack in Rails

Saturday, July 25, 2009

Page 22: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 23: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 24: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 25: And the Greatest of These Is ... Space

> rake middlewareuse Rack::Lockuse ActionDispatch::ShowExceptions, [true]use ActionDispatch::Callbacks, [true]use ActionDispatch::Rescue, [#<Method: ...>]use ActionDispatch::Session::CookieStore, [{...}]use ActionDispatch::ParamsParseruse Rack::MethodOverrideuse Rack::Headuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacherun ActionController::Dispatcher.new

Saturday, July 25, 2009

Page 26: And the Greatest of These Is ... Space

> rake middlewareuse Rack::Lockuse ActionDispatch::ShowExceptions, [true]use ActionDispatch::Callbacks, [true]use ActionDispatch::Rescue, [#<Method: ...>]use ActionDispatch::Session::CookieStore, [{...}]use ActionDispatch::ParamsParseruse Rack::MethodOverrideuse Rack::Headuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacherun ActionController::Dispatcher.new

> rake middlewareuse Rack::Lockuse ActionDispatch::ShowExceptions, [true]use ActionDispatch::Callbacks, [true]use ActionDispatch::Rescue, [#<Method: ...>]use ActionDispatch::Session::CookieStore, [{...}]use ActionDispatch::ParamsParseruse Rack::MethodOverrideuse Rack::Headuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacherun ActionController::Dispatcher.new

Saturday, July 25, 2009

Page 27: And the Greatest of These Is ... Space

app = Rack::Builder.new { use Rails::Rack::LogTailer unless options[:detach] use Rails::Rack::Debugger if options[:debugger]

map "/" do use Rails::Rack::Static run ActionController::Dispatcher.new end}.to_app

Saturday, July 25, 2009

Page 28: And the Greatest of These Is ... Space

Rails::Initializer.run do |config| config.middleware.insert_before Rack::Head, Ben::Asplode config.middleware.swap Rack::Lock, Ben::Lock config.middleware.use Rack::MailExceptionsend

Saturday, July 25, 2009

Page 29: And the Greatest of These Is ... Space

Rails::Initializer.run do |config| config.middleware.insert_before Rack::Head, Ben::Asplode config.middleware.swap Rack::Lock, Ben::Lock config.middleware.use Rack::MailExceptionsend

# in config/initializers/middlewares.rb

ActionController::Dispatcher.middleware.insert_before 'Rack::Head', AppenderActionController::Dispatcher.middleware.delete 'Rack::Lock'ActionController::Dispatcher.middleware.use Prepender

Saturday, July 25, 2009

Page 30: And the Greatest of These Is ... Space

Metalflickr: lrargerich

Saturday, July 25, 2009

Page 31: And the Greatest of These Is ... Space

http://www.kiwibean.com/

Saturday, July 25, 2009

Page 32: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 33: And the Greatest of These Is ... Space

EXPAND: testing metalPLEASE STAND BYTHIS IS ONLY A TEST

Saturday, July 25, 2009

Page 34: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 35: And the Greatest of These Is ... Space

METAL

Sinatra

Saturday, July 25, 2009

Page 36: And the Greatest of These Is ... Space

Cool Tricks

Saturday, July 25, 2009

Page 37: And the Greatest of These Is ... Space

Rack::Bugflickr: catdancing

Saturday, July 25, 2009

Page 38: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 39: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 40: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 41: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 42: And the Greatest of These Is ... Space

requires </body>

Saturday, July 25, 2009

Page 43: And the Greatest of These Is ... Space

Progressive CachingSaturday, July 25, 2009

Page 44: And the Greatest of These Is ... Space

Progressive CachingSaturday, July 25, 2009

Page 45: And the Greatest of These Is ... Space

Progressive CachingSaturday, July 25, 2009

Page 46: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 47: And the Greatest of These Is ... Space

class SessionsController < ApplicationController def create # ... session[:personalize] = { :logged_in => true, :quicklist => current_user.quicklist.episode_ids, :subscriptions => current_user.subscription_ids } endend

Saturday, July 25, 2009

Page 48: And the Greatest of These Is ... Space

class ChannelsController < ApplicationController caches_page :show def show @channel = Channel.find(params[:id]) endend

Saturday, July 25, 2009

Page 49: And the Greatest of These Is ... Space

$(document).ready(function() { $.getJSON('/personalize', function(data) {

// identify quicklisted episodes $.each(data['quicklist'], function() { $('#episode_'+this).addClass('listed'); }); // switch navigation if (data['logged_in']) { $('#logged_in_nav').show(); } // etc. });});

Saturday, July 25, 2009

Page 50: And the Greatest of These Is ... Space

class Personalizer def self.call(env) if env["PATH_INFO"] =~ /^/personalize/ [ 200, {"Content-Type" => "application/javascript"}, env['rack.session'][:personalize].to_json ] else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end endend

Saturday, July 25, 2009

Page 51: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 52: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 53: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 54: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 55: And the Greatest of These Is ... Space

standard

progressive 0.0960.039

0.617

class PullList def self.call(env) if env["PATH_INFO"] =~ /^\/pulls/ [ 200, {"Content-Type" => "application/javascript"}, [Pull.by_user(user).for_date(date).map {|i| i.item_id}.to_json]] else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end endend

Saturday, July 25, 2009

Page 56: And the Greatest of These Is ... Space

class PullList def self.call(env) if env["PATH_INFO"] =~ /^\/pulls/ [ 200, {"Content-Type" => "application/javascript"}, [env['rack.session'][:pulls].to_json] ] else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end endend

standard

progressive

progressive v2 0.023

0.096

0.043

0.039

0.617

Saturday, July 25, 2009

Page 57: And the Greatest of These Is ... Space

DIY

Saturday, July 25, 2009

Page 58: And the Greatest of These Is ... Space

requestapplication

response

middleware

middleware

Saturday, July 25, 2009

Page 59: And the Greatest of These Is ... Space

Rack::EmbiggenerSaturday, July 25, 2009

Page 60: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 61: And the Greatest of These Is ... Space

class Embiggener < Test::Unit::TestCase def test_embiggener_should_embiggen_known_url body = ["Hello! I'm at http://bit.ly/31IqMl"] assert_equal ["Hello! I'm at http://cnn.com"], Rack:: Embiggener.embiggen_urls(body) end

def test_embiggener_should_embiggen_multiple_urls body = [ "Hello! I'm at http://bit.ly/31IqMl", "And I'm at http://bit.ly/31IqMl" ] assert_equal [ "Hello! I'm at http://cnn.com", "And I'm at http://cnn.com" ], Rack::Embiggener.embiggen_urls(body) endend

Saturday, July 25, 2009

Page 62: And the Greatest of These Is ... Space

module Rack class Embiggener def self.embiggen_urls(original_body, login, key) new_body = [] original_body.each { |line| bits = line.scan(/(http:\/\/bit\.ly\/(.{6}))/)

new_body << bits.uniq.inject(line) do |body, bit| original_bit, hash = *bit new_url = embiggened_url(hash, login, key) body.gsub(original_bit, new_url) if new_url end } new_body end

# ... endend

Saturday, July 25, 2009

Page 63: And the Greatest of These Is ... Space

module Rack class Embiggener # ...

def self.embiggened_url(hash, login, key) url = [ "http://api.bit.ly/expand?version=2.0.1", "shortUrl=http://bit.ly/#{hash}", "login=#{login}", "apiKey=#{key}" ].join('&') response = JSON.parse(Net::HTTP.get_response(URI.parse(url))) if response['statusCode'] = 'OK' embiggened_url = response['results'][hash]['longUrl'] end end

# ... endend

Saturday, July 25, 2009

Page 64: And the Greatest of These Is ... Space

module Rack class Embiggener # ... attr_accessor :api_login, :api_key def initialize(app, api_login, api_key) @app = app @api_login = api_login @api_key = api_key end

def call(env) status, headers, body = @app.call(env) headers.delete('Content-Length') response = Rack::Response.new( Rack::Embiggener.embiggen_urls(body, api_login, api_hash), status, headers ) response.finish return response.to_a end endend

Saturday, July 25, 2009

Page 65: And the Greatest of These Is ... Space

module Rack class Embiggener def self.embiggen_urls(original_body, login, key) new_body = [] original_body.each { |line| bits = line.scan(/bit\:(\w+?)/)

new_body << bits.uniq.inject(line) do |body, bit| hash = bit.first original_bit = "bit:#{hash}" new_url = embiggened_url(hash, login, key) body.gsub(original_bit, new_url) if new_url end } new_body

end # ... endend

Saturday, July 25, 2009

Page 66: And the Greatest of These Is ... Space

module Rack class Embiggener # ...

def self.embiggened_url(hash, login, key) url = [ "http://api.bit.ly/expand?version=2.0.1", "hash=#{hash}", "login=#{login}", "apiKey=#{key}" ].join('&') response = JSON.parse(Net::HTTP.get_response(URI.parse(url))) if response['statusCode'] = 'OK' embiggened_url = response['results'][hash]['longUrl'] end end

# ... endend

Saturday, July 25, 2009

Page 67: And the Greatest of These Is ... Space

WARNINGexception handling

Saturday, July 25, 2009

Page 68: And the Greatest of These Is ... Space

WARNINGexception handling

formerly:

Saturday, July 25, 2009

Page 69: And the Greatest of These Is ... Space

Rack::Hoptoad** unofficial; thoughtbot is not responsible for this middleware; do not taunt rack::hoptoad; pregnant women should consult their doctors before using rack::hoptoad

Saturday, July 25, 2009

Page 70: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 71: And the Greatest of These Is ... Space

> rake middlewareuse Rack::Lockuse ActionDispatch::ShowExceptions, [true]use ActionDispatch::Callbacks, [true]use ActionDispatch::Rescue, [#<Method: ...>]use ActionDispatch::Session::CookieStore, [{...}]use ActionDispatch::ParamsParseruse Rack::MethodOverrideuse Rack::Headuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacherun ActionController::Dispatcher.new

Saturday, July 25, 2009

Page 72: And the Greatest of These Is ... Space

ActionController::Dispatcher.middleware.delete ActionDispatch::ShowExceptionsActionController::Dispatcher.middleware.delete ActionDispatch::Rescue ActionController::Dispatcher.middleware.use 'Rack::Hoptoad', 'my-api-key'ActionController::Dispatcher.middleware.use 'Rack::ShowExceptions'

Saturday, July 25, 2009

Page 73: And the Greatest of These Is ... Space

module Rack class Hoptoad def initialize(app, api_key) @app = app @api_key = api_key end

def call(env) @app.call(env) rescue => exception notify_hoptoad(exception, env) raise exception end

# ... endend

Saturday, July 25, 2009

Page 74: And the Greatest of These Is ... Space

module Rack class Hoptoad def notify_hoptoad(exception, env) headers = { 'Content-type' => 'application/x-yaml', 'Accept' => 'text/xml, application/xml' } url = URI.parse("http://hoptoadapp.com/notices")

http = Net::HTTP.new(url.host, url.port)

data = { :api_key => @api_key, :error_message => "#{exception.class}: #{exception}", :backtrace => exception.backtrace, :request => {}, :session => env['rack.session'], :environment => env }

response = http.post( url.path, stringify_keys(:notice => data).to_yaml, headers ) if response != Net::HTTPSuccess # Hoptoad post failed end end endend

Saturday, July 25, 2009

Page 75: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 76: And the Greatest of These Is ... Space

Intangibles

Saturday, July 25, 2009

Page 77: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 78: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 79: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 80: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 81: And the Greatest of These Is ... Space

Saturday, July 25, 2009

Page 82: And the Greatest of These Is ... Space

Thank You

ben scofield - @bscofield - http://www.viget.com/extend - http://www.speakerrate.com/bscofield

Saturday, July 25, 2009