SlideShare a Scribd company logo
1 of 82
Download to read offline
And the Greatest of These Is...
           Rack Support
            Ben Scoļ¬eld ā€“ Viget Labs




Saturday, July 25, 2009
Saturday, July 25, 2009
Application Templates
Saturday, July 25, 2009
Nested Attribute Assignment
  ļ¬‚ickr: angelrays


Saturday, July 25, 2009
ActiveRecord::Base#touch
  ļ¬‚ickr: jjjohn


Saturday, July 25, 2009
DB Seeding
  ļ¬‚ickr: richardthomas78


Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Rack


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




Saturday, July 25, 2009
Saturday, July 25, 2009
request
                          application
                           response
Saturday, July 25, 2009
request
                             middleware

                          application
                             middleware

                           response
Saturday, July 25, 2009
Saturday, July 25, 2009
Rack::Proļ¬ler
  ļ¬‚ickr: oberazzi


Saturday, July 25, 2009
Rack::MailExceptions
  ļ¬‚ickr: warmnfuzzy


Saturday, July 25, 2009
Rack::Cache
  ļ¬‚ickr: timpatterson


Saturday, July 25, 2009
rack::cascade

 Rack::Cascade
  ļ¬‚ickr: _at


Saturday, July 25, 2009
Rack in Rails


Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
> rake middleware
      use Rack::Lock
      use ActionDispatch::ShowExceptions, [true]
      use ActionDispatch::Callbacks, [true]
      use ActionDispatch::Rescue, [#<Method: ...>]
      use ActionDispatch::Session::CookieStore, [{...}]
      use ActionDispatch::ParamsParser
      use Rack::MethodOverride
      use Rack::Head
      use ActiveRecord::ConnectionAdapters::ConnectionManagement
      use ActiveRecord::QueryCache
      run ActionController::Dispatcher.new




Saturday, July 25, 2009
> rake middleware
      use Rack::Lock
      use ActionDispatch::ShowExceptions, [true]
      use ActionDispatch::Callbacks, [true]
      use ActionDispatch::Rescue, [#<Method: ...>]
      use ActionDispatch::Session::CookieStore, [{...}]
      use ActionDispatch::ParamsParser
      use Rack::MethodOverride
      use Rack::Head
      use ActiveRecord::ConnectionAdapters::ConnectionManagement
      use ActiveRecord::QueryCache
      run ActionController::Dispatcher.new




Saturday, July 25, 2009
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
Rails::Initializer.run do |config|
        config.middleware.insert_before Rack::Head, Ben::Asplode
        config.middleware.swap          Rack::Lock, Ben::Lock
        config.middleware.use            Rack::MailExceptions
      end




Saturday, July 25, 2009
# in config/initializers/middlewares.rb
      Rails::Initializer.run do |config|
        config.middleware.insert_before Rack::Head, Ben::Asplode
      ActionController::Dispatcher.middleware.insert_before 'Rack::Head', Appender
        config.middleware.swap          Rack::Lock, Ben::Lock
      ActionController::Dispatcher.middleware.delete 'Rack::Lock'
        config.middleware.use            Rack::MailExceptions
      ActionController::Dispatcher.middleware.use Prepender
      end




Saturday, July 25, 2009
Metal
  ļ¬‚ickr: lrargerich


Saturday, July 25, 2009
http://www.kiwibean.com/



Saturday, July 25, 2009
Saturday, July 25, 2009
PLEASE testing metalBY
                             EXPAND:
                                     STAND
                          THIS IS ONLY A TEST


Saturday, July 25, 2009
Saturday, July 25, 2009
METAL
                           Sinatra

Saturday, July 25, 2009
Cool Tricks


Saturday, July 25, 2009
Rack::Bug
  ļ¬‚ickr: catdancing


Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
requires
                          </body>
Saturday, July 25, 2009
Progressive Caching
Saturday, July 25, 2009
Progressive Caching
Saturday, July 25, 2009
Progressive Caching
Saturday, July 25, 2009
Saturday, July 25, 2009
class SessionsController < ApplicationController
        def create
          # ...
          session[:personalize] = {
            :logged_in => true,
            :quicklist => current_user.quicklist.episode_ids,
            :subscriptions => current_user.subscription_ids
          }
        end
      end




Saturday, July 25, 2009
class ChannelsController < ApplicationController
        caches_page :show

        def show
          @channel = Channel.find(params[:id])
        end
      end




Saturday, July 25, 2009
$(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
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
        end
      end




Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
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
        end
      end




             standard     0.617




       progressive        0.039 0.096




Saturday, July 25, 2009
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
        end
      end




             standard     0.617



       progressive        0.039 0.096



  progressive v2          0.043 0.023




Saturday, July 25, 2009
DIY


Saturday, July 25, 2009
request
                             middleware

                          application
                             middleware

                           response
Saturday, July 25, 2009
Rack::Embiggener
Saturday, July 25, 2009
Saturday, July 25, 2009
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)
        end
      end




Saturday, July 25, 2009
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

          # ...
        end
      end




Saturday, July 25, 2009
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

          # ...
        end
      end




Saturday, July 25, 2009
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
        end
      end




Saturday, July 25, 2009
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

          # ...
        end
      end




Saturday, July 25, 2009
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

          # ...
        end
      end




Saturday, July 25, 2009
WARNING       exception handling



Saturday, July 25, 2009
formerly:


            WARNING       exception handling



Saturday, July 25, 2009
Rack::Hoptoad*
  * unoļ¬ƒcial; 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
Saturday, July 25, 2009
> rake middleware
      use Rack::Lock
      use ActionDispatch::ShowExceptions, [true]
      use ActionDispatch::Callbacks, [true]
      use ActionDispatch::Rescue, [#<Method: ...>]
      use ActionDispatch::Session::CookieStore, [{...}]
      use ActionDispatch::ParamsParser
      use Rack::MethodOverride
      use Rack::Head
      use ActiveRecord::ConnectionAdapters::ConnectionManagement
      use ActiveRecord::QueryCache
      run ActionController::Dispatcher.new




Saturday, July 25, 2009
ActionController::Dispatcher.middleware.delete ActionDispatch::ShowExceptions
      ActionController::Dispatcher.middleware.delete ActionDispatch::Rescue

      ActionController::Dispatcher.middleware.use   'Rack::Hoptoad', 'my-api-key'
      ActionController::Dispatcher.middleware.use   'Rack::ShowExceptions'




Saturday, July 25, 2009
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

          # ...
        end
      end




Saturday, July 25, 2009
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
        end
      end

Saturday, July 25, 2009
Saturday, July 25, 2009
Intangibles


Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Saturday, July 25, 2009
Thank You
         ben scoļ¬eld - @bscoļ¬eld - http://www.viget.com/extend - http://www.speakerrate.com/bscoļ¬eld
Saturday, July 25, 2009

More Related Content

What's hot

Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)andrewnacin
Ā 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creationbenalman
Ā 
An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.jscodeofficer
Ā 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudHiro Asari
Ā 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoojeresig
Ā 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty HammerBen Scofield
Ā 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...Codemotion
Ā 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
Ā 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkBen Scofield
Ā 
jQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionjQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionPaul Irish
Ā 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncioJames Saryerwinnie
Ā 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud CastlesBen Scofield
Ā 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
Ā 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Kris Wallsmith
Ā 
Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2nottings
Ā 
SEMAC 2011 - Apresentando Ruby e Ruby on Rails
SEMAC 2011 - Apresentando Ruby e Ruby on RailsSEMAC 2011 - Apresentando Ruby e Ruby on Rails
SEMAC 2011 - Apresentando Ruby e Ruby on RailsFabio Akita
Ā 
Node.js for PHP developers
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developersAndrew Eddie
Ā 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
Ā 

What's hot (19)

Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
Ā 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creation
Ā 
An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.js
Ā 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the Cloud
Ā 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoo
Ā 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty Hammer
Ā 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
Ā 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Ā 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
Ā 
jQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionjQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & Compression
Ā 
Symfony 2
Symfony 2Symfony 2
Symfony 2
Ā 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncio
Ā 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
Ā 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
Ā 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)
Ā 
Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2
Ā 
SEMAC 2011 - Apresentando Ruby e Ruby on Rails
SEMAC 2011 - Apresentando Ruby e Ruby on RailsSEMAC 2011 - Apresentando Ruby e Ruby on Rails
SEMAC 2011 - Apresentando Ruby e Ruby on Rails
Ā 
Node.js for PHP developers
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developers
Ā 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
Ā 

Similar to And the Greatest of These Is ... Space

How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
Ā 
Building a desktop app with HTTP::Engine, SQLite and jQuery
Building a desktop app with HTTP::Engine, SQLite and jQueryBuilding a desktop app with HTTP::Engine, SQLite and jQuery
Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
Ā 
Rails For Kids 2009
Rails For Kids 2009Rails For Kids 2009
Rails For Kids 2009Fabio Akita
Ā 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
Ā 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers StealBen Scofield
Ā 
Keeping It Small with Slim
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with SlimRaven Tools
Ā 
StirTrek 2018 - Rapid API Development with Sails
StirTrek 2018 - Rapid API Development with SailsStirTrek 2018 - Rapid API Development with Sails
StirTrek 2018 - Rapid API Development with SailsJustin James
Ā 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2Kacper Gunia
Ā 
RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜
RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜
RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS ć€œå“‡ä¹‹ ęø…ę°“
Ā 
QConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes Web
QConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes WebQConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes Web
QConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes WebFabio Akita
Ā 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the BasicsMichael Koby
Ā 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTPMustafa TURAN
Ā 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup PerformanceJustin Cataldo
Ā 
Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascriptaglemann
Ā 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
Ā 
SilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringSilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringIngo Schommer
Ā 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
Ā 

Similar to And the Greatest of These Is ... Space (20)

How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
Ā 
Building a desktop app with HTTP::Engine, SQLite and jQuery
Building a desktop app with HTTP::Engine, SQLite and jQueryBuilding a desktop app with HTTP::Engine, SQLite and jQuery
Building a desktop app with HTTP::Engine, SQLite and jQuery
Ā 
Rails For Kids 2009
Rails For Kids 2009Rails For Kids 2009
Rails For Kids 2009
Ā 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
Ā 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
Ā 
Keeping It Small with Slim
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with Slim
Ā 
StirTrek 2018 - Rapid API Development with Sails
StirTrek 2018 - Rapid API Development with SailsStirTrek 2018 - Rapid API Development with Sails
StirTrek 2018 - Rapid API Development with Sails
Ā 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2
Ā 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
Ā 
Elegant APIs
Elegant APIsElegant APIs
Elegant APIs
Ā 
RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜
RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜
RESTful API 悒 Chalice 恧ē“č§£ć 怜 Python Serverless Microframework for AWS 怜
Ā 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
Ā 
QConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes Web
QConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes WebQConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes Web
QConSP 2015 - Dicas de Performance para AplicacĢ§oĢƒes Web
Ā 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
Ā 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
Ā 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
Ā 
Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascript
Ā 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
Ā 
SilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringSilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript Refactoring
Ā 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Ā 

More from Ben Scofield

How to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 StepsHow to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 StepsBen Scofield
Ā 
Building Cloud Castles - LRUG
Building Cloud Castles - LRUGBuilding Cloud Castles - LRUG
Building Cloud Castles - LRUGBen Scofield
Ā 
Thinking Small
Thinking SmallThinking Small
Thinking SmallBen Scofield
Ā 
Open Source: A Call to Arms
Open Source: A Call to ArmsOpen Source: A Call to Arms
Open Source: A Call to ArmsBen Scofield
Ā 
Intentionality: Choice and Mastery
Intentionality: Choice and MasteryIntentionality: Choice and Mastery
Intentionality: Choice and MasteryBen Scofield
Ā 
Mastery or Mediocrity
Mastery or MediocrityMastery or Mediocrity
Mastery or MediocrityBen Scofield
Ā 
Mind Control - DevNation Atlanta
Mind Control - DevNation AtlantaMind Control - DevNation Atlanta
Mind Control - DevNation AtlantaBen Scofield
Ā 
Understanding Mastery
Understanding MasteryUnderstanding Mastery
Understanding MasteryBen Scofield
Ā 
Mind Control: Psychology for the Web
Mind Control: Psychology for the WebMind Control: Psychology for the Web
Mind Control: Psychology for the WebBen Scofield
Ā 
The State of NoSQL
The State of NoSQLThe State of NoSQL
The State of NoSQLBen Scofield
Ā 
NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010Ben Scofield
Ā 
NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)Ben Scofield
Ā 
Charlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is HardCharlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is HardBen Scofield
Ā 
The Future of Data
The Future of DataThe Future of Data
The Future of DataBen Scofield
Ā 
WindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is HardWindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is HardBen Scofield
Ā 
"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative Databases"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative DatabasesBen Scofield
Ā 
Mind Control on the Web
Mind Control on the WebMind Control on the Web
Mind Control on the WebBen Scofield
Ā 
How the Geeks Inherited the Earth
How the Geeks Inherited the EarthHow the Geeks Inherited the Earth
How the Geeks Inherited the EarthBen Scofield
Ā 
"Comics" Is Hard: Domain Modeling Challenges
"Comics" Is Hard: Domain Modeling Challenges"Comics" Is Hard: Domain Modeling Challenges
"Comics" Is Hard: Domain Modeling ChallengesBen Scofield
Ā 

More from Ben Scofield (20)

How to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 StepsHow to Be Awesome in 2.5 Steps
How to Be Awesome in 2.5 Steps
Ā 
Building Cloud Castles - LRUG
Building Cloud Castles - LRUGBuilding Cloud Castles - LRUG
Building Cloud Castles - LRUG
Ā 
Thinking Small
Thinking SmallThinking Small
Thinking Small
Ā 
Open Source: A Call to Arms
Open Source: A Call to ArmsOpen Source: A Call to Arms
Open Source: A Call to Arms
Ā 
Ship It
Ship ItShip It
Ship It
Ā 
Intentionality: Choice and Mastery
Intentionality: Choice and MasteryIntentionality: Choice and Mastery
Intentionality: Choice and Mastery
Ā 
Mastery or Mediocrity
Mastery or MediocrityMastery or Mediocrity
Mastery or Mediocrity
Ā 
Mind Control - DevNation Atlanta
Mind Control - DevNation AtlantaMind Control - DevNation Atlanta
Mind Control - DevNation Atlanta
Ā 
Understanding Mastery
Understanding MasteryUnderstanding Mastery
Understanding Mastery
Ā 
Mind Control: Psychology for the Web
Mind Control: Psychology for the WebMind Control: Psychology for the Web
Mind Control: Psychology for the Web
Ā 
The State of NoSQL
The State of NoSQLThe State of NoSQL
The State of NoSQL
Ā 
NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010NoSQL @ CodeMash 2010
NoSQL @ CodeMash 2010
Ā 
NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)NoSQL: Death to Relational Databases(?)
NoSQL: Death to Relational Databases(?)
Ā 
Charlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is HardCharlotte.rb - "Comics" Is Hard
Charlotte.rb - "Comics" Is Hard
Ā 
The Future of Data
The Future of DataThe Future of Data
The Future of Data
Ā 
WindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is HardWindyCityRails - "Comics" Is Hard
WindyCityRails - "Comics" Is Hard
Ā 
"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative Databases"Comics" Is Hard: Alternative Databases
"Comics" Is Hard: Alternative Databases
Ā 
Mind Control on the Web
Mind Control on the WebMind Control on the Web
Mind Control on the Web
Ā 
How the Geeks Inherited the Earth
How the Geeks Inherited the EarthHow the Geeks Inherited the Earth
How the Geeks Inherited the Earth
Ā 
"Comics" Is Hard: Domain Modeling Challenges
"Comics" Is Hard: Domain Modeling Challenges"Comics" Is Hard: Domain Modeling Challenges
"Comics" Is Hard: Domain Modeling Challenges
Ā 

Recently uploaded

Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
Ā 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
Ā 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
Ā 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
Ā 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfOverkill Security
Ā 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
Ā 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
Ā 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
Ā 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
Ā 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
Ā 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
Ā 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
Ā 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
Ā 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
Ā 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
Ā 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
Ā 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
Ā 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
Ā 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
Ā 

Recently uploaded (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
Ā 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
Ā 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
Ā 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
Ā 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
Ā 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Ā 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Ā 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
Ā 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
Ā 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
Ā 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
Ā 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Ā 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
Ā 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Ā 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Ā 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
Ā 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
Ā 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Ā 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
Ā 

And the Greatest of These Is ... Space

  • 1. And the Greatest of These Is... Rack Support Ben Scoļ¬eld ā€“ Viget Labs Saturday, July 25, 2009
  • 4. Nested Attribute Assignment ļ¬‚ickr: angelrays Saturday, July 25, 2009
  • 5. ActiveRecord::Base#touch ļ¬‚ickr: jjjohn Saturday, July 25, 2009
  • 6. DB Seeding ļ¬‚ickr: richardthomas78 Saturday, July 25, 2009
  • 12. def call(env) [ status, # 200 headers, # {"Content-Type" => "text/html"} body # ["<html>...</html>"] ] end Saturday, July 25, 2009
  • 14. request application response Saturday, July 25, 2009
  • 15. request middleware application middleware response Saturday, July 25, 2009
  • 17. Rack::Proļ¬ler ļ¬‚ickr: oberazzi Saturday, July 25, 2009
  • 18. Rack::MailExceptions ļ¬‚ickr: warmnfuzzy Saturday, July 25, 2009
  • 19. Rack::Cache ļ¬‚ickr: timpatterson Saturday, July 25, 2009
  • 20. rack::cascade Rack::Cascade ļ¬‚ickr: _at Saturday, July 25, 2009
  • 21. Rack in Rails Saturday, July 25, 2009
  • 25. > rake middleware use Rack::Lock use ActionDispatch::ShowExceptions, [true] use ActionDispatch::Callbacks, [true] use ActionDispatch::Rescue, [#<Method: ...>] use ActionDispatch::Session::CookieStore, [{...}] use ActionDispatch::ParamsParser use Rack::MethodOverride use Rack::Head use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache run ActionController::Dispatcher.new Saturday, July 25, 2009
  • 26. > rake middleware use Rack::Lock use ActionDispatch::ShowExceptions, [true] use ActionDispatch::Callbacks, [true] use ActionDispatch::Rescue, [#<Method: ...>] use ActionDispatch::Session::CookieStore, [{...}] use ActionDispatch::ParamsParser use Rack::MethodOverride use Rack::Head use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache run ActionController::Dispatcher.new Saturday, July 25, 2009
  • 27. 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
  • 28. Rails::Initializer.run do |config| config.middleware.insert_before Rack::Head, Ben::Asplode config.middleware.swap Rack::Lock, Ben::Lock config.middleware.use Rack::MailExceptions end Saturday, July 25, 2009
  • 29. # in config/initializers/middlewares.rb Rails::Initializer.run do |config| config.middleware.insert_before Rack::Head, Ben::Asplode ActionController::Dispatcher.middleware.insert_before 'Rack::Head', Appender config.middleware.swap Rack::Lock, Ben::Lock ActionController::Dispatcher.middleware.delete 'Rack::Lock' config.middleware.use Rack::MailExceptions ActionController::Dispatcher.middleware.use Prepender end Saturday, July 25, 2009
  • 30. Metal ļ¬‚ickr: lrargerich Saturday, July 25, 2009
  • 33. PLEASE testing metalBY EXPAND: STAND THIS IS ONLY A TEST Saturday, July 25, 2009
  • 35. METAL Sinatra Saturday, July 25, 2009
  • 37. Rack::Bug ļ¬‚ickr: catdancing Saturday, July 25, 2009
  • 42. requires </body> Saturday, July 25, 2009
  • 47. class SessionsController < ApplicationController def create # ... session[:personalize] = { :logged_in => true, :quicklist => current_user.quicklist.episode_ids, :subscriptions => current_user.subscription_ids } end end Saturday, July 25, 2009
  • 48. class ChannelsController < ApplicationController caches_page :show def show @channel = Channel.find(params[:id]) end end Saturday, July 25, 2009
  • 49. $(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
  • 50. 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 end end Saturday, July 25, 2009
  • 55. 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 end end standard 0.617 progressive 0.039 0.096 Saturday, July 25, 2009
  • 56. 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 end end standard 0.617 progressive 0.039 0.096 progressive v2 0.043 0.023 Saturday, July 25, 2009
  • 58. request middleware application middleware response Saturday, July 25, 2009
  • 61. 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) end end Saturday, July 25, 2009
  • 62. 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 # ... end end Saturday, July 25, 2009
  • 63. 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 # ... end end Saturday, July 25, 2009
  • 64. 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 end end Saturday, July 25, 2009
  • 65. 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 # ... end end Saturday, July 25, 2009
  • 66. 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 # ... end end Saturday, July 25, 2009
  • 67. WARNING exception handling Saturday, July 25, 2009
  • 68. formerly: WARNING exception handling Saturday, July 25, 2009
  • 69. Rack::Hoptoad* * unoļ¬ƒcial; 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
  • 71. > rake middleware use Rack::Lock use ActionDispatch::ShowExceptions, [true] use ActionDispatch::Callbacks, [true] use ActionDispatch::Rescue, [#<Method: ...>] use ActionDispatch::Session::CookieStore, [{...}] use ActionDispatch::ParamsParser use Rack::MethodOverride use Rack::Head use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache run ActionController::Dispatcher.new Saturday, July 25, 2009
  • 72. ActionController::Dispatcher.middleware.delete ActionDispatch::ShowExceptions ActionController::Dispatcher.middleware.delete ActionDispatch::Rescue ActionController::Dispatcher.middleware.use 'Rack::Hoptoad', 'my-api-key' ActionController::Dispatcher.middleware.use 'Rack::ShowExceptions' Saturday, July 25, 2009
  • 73. 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 # ... end end Saturday, July 25, 2009
  • 74. 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 end end Saturday, July 25, 2009
  • 82. Thank You ben scoļ¬eld - @bscoļ¬eld - http://www.viget.com/extend - http://www.speakerrate.com/bscoļ¬eld Saturday, July 25, 2009