SlideShare a Scribd company logo
1 of 77
And the Greatest of These Is...
Rack Support
Ben Sco eld – Viget Labs
#?forben
Application Templates
Nested Attribute Assignment
ickr: angelrays
ActiveRecord::Base#touch
ickr: jjjohn
Rack
def call(env)
 [
   status, # 200
   headers, # {quot;Content-Typequot; => quot;text/htmlquot;}
   body    # [quot;<html>...</html>quot;]
 ]
end
request
application
 response
request
   middleware

application
   middleware

 response
Rack::Pro ler
ickr: oberazzi
Rack::MailExceptions
ickr: warmnfuzzy
Rack::Cache
ickr: timpatterson
rack::cascade

Rack::Cascade
ickr: _at
Rack in Rails
> rake middleware
use Rack::Lock
use ActionDispatch::Failsafe
use ActionDispatch::ShowExceptions, [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
> rake middleware
use Rack::Lock
use ActionDispatch::Failsafe
use ActionDispatch::ShowExceptions, [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
app = Rack::Builder.new {
 use Rails::Rack::LogTailer unless options[:detach]
 use Rails::Rack::Debugger if options[:debugger]

  map quot;/quot; do
   use Rails::Rack::Static
   run ActionController::Dispatcher.new
  end
}.to_app
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
Metal
ickr: lrargerich
http://www.kiwibean.com/
PLEASE testing metalBY
           STAND
   EXPAND:
THIS IS ONLY A TEST
METAL
 Sinatra
Cool Tricks
Rack::Bug
ickr: catdancing
requires
</body>
Progressive Caching
Progressive Caching
Progressive Caching
class SessionsController < ApplicationController
 def create
   # ...
   session[:personalize] = {
     :logged_in => true,
     :quicklist => current_user.quicklist.episode_ids,
     :subscriptions => current_user.subscription_ids
   }
 end
end
class ChannelsController < ApplicationController
 caches_page :show

 def show
  @channel = Channel.find(params[:id])
 end
end
$(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.
  });
});
class Personalizer
 def self.call(env)
   if env[quot;PATH_INFOquot;] =~ /^/personalize/
     [
       200,
       {quot;Content-Typequot; => quot;application/javascriptquot;},
       env['rack.session'][:personalize].to_json
     ]
   else
     [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]]
   end
 end
end
class PullList
 def self.call(env)
   if env[quot;PATH_INFOquot;] =~ /^/pulls/
     [
       200,
      {quot;Content-Typequot; => quot;application/javascriptquot;},
      [Pull.by_user(user).for_date(date).map {|i| i.item_id}.to_json]]
   else
     [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]]
   end
 end
end




    standard       0.617




 progressive       0.039 0.096
class PullList
   def self.call(env)
     if env[quot;PATH_INFOquot;] =~ /^/pulls/
       [
         200,
         {quot;Content-Typequot; => quot;application/javascriptquot;},
         [env['rack.session'][:pulls].to_json]
       ]
     else
       [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]]
     end
   end
  end




      standard      0.617



   progressive      0.039 0.096



progressive v2      0.043 0.023
DIY
request
   middleware

application
   middleware

 response
Rack::Embiggener
class Embiggener < Test::Unit::TestCase
 def test_embiggener_should_embiggen_known_url
   body = [quot;Hello! I'm at http://tinyurl.com/cjmhvaquot;]
   assert_equal [quot;Hello! I'm at http://www.culann.comquot;],
            Rack:: Embiggener.embiggen_urls(body)
 end

 def test_embiggener_should_embiggen_multiple_urls
  body = [
    quot;Hello! I'm at http://tinyurl.com/cjmhvaquot;,
    quot;And I'm at http://tinyurl.com/cjmhvaquot;
  ]

  assert_equal [
    quot;Hello! I'm at http://www.culann.comquot;,
    quot;And I'm at http://www.culann.comquot;
  ], Rack::Embiggener.embiggen_urls(body)
 end
end
module Rack
 class Embiggener
  def self.embiggen_urls(original_body)
    new_body = []
    original_body.each { |line|
     tinys = line.scan(/(http://(?:www.)?tinyurl.com/(.{6}))/)
     new_body << tinys.uniq.inject(line) do |body, tiny|
       original_tiny = tiny[0]
       preview_url = quot;http://preview.tinyurl.com/#{tiny[1]}quot;
       response = Net::HTTP.get_response(URI.parse(preview_url))
       embiggened_url = response.body.match(/redirecturlquot; href=quot;(.*)quot;>/)[1]

        body.gsub(original_tiny, embiggened_url)
       end
   }
   new_body
  end

  # ...
 end
end
module Rack
 class Embiggener
  # ...

  def initialize(app)
   @app = app
  end

  def call(env)
   status, headers, body = @app.call(env)
   headers.delete('Content-Length')

   response = Rack::Response.new(
     Rack::Embiggener.embiggen_urls(body),
     status,
     headers
   )
   response.finish

    return response.to_a
  end
 end
end
WARNING
 exception handling
formerly:


WARNING
 exception handling
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
> rake middleware
use Rack::Lock
use ActionDispatch::Failsafe
use ActionDispatch::ShowExceptions, [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
Rails::Initializer.run do |config|
 # ...

 config.middleware.delete ActionDispatch::ShowExceptions
 config.middleware.delete ActionDispatch::Rescue

 config.middleware.use       'Rack::Hoptoad', 'my-hoptoad-api-key'
 config.middleware.use       'Rack::ShowExceptions'
end
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
module Rack
 class Hoptoad
  def notify_hoptoad(exception, env)
    headers = {
      'Content-type' => 'application/x-yaml',
      'Accept' => 'text/xml, application/xml'
    }
    url = URI.parse(quot;http://hoptoadapp.com/noticesquot;)

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

   data = {
     :api_key    => @api_key,
     :error_message => quot;#{exception.class}: #{exception}quot;,
     :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
Intangibles
Thank You
ben sco eld - @bsco eld - http://www.viget.com/extend - http://www.speakerrate.com/bsco eld

More Related Content

What's hot

Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
Kris Wallsmith
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
Jay Shirley
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 

What's hot (20)

Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101
 
Let's play a game with blackfire player
Let's play a game with blackfire playerLet's play a game with blackfire player
Let's play a game with blackfire player
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
Desenvolvendo APIs usando Rails - Guru SC 2012
Desenvolvendo APIs usando Rails - Guru SC 2012Desenvolvendo APIs usando Rails - Guru SC 2012
Desenvolvendo APIs usando Rails - Guru SC 2012
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Php Unit With Zend Framework Zendcon09
Php Unit With Zend Framework   Zendcon09Php Unit With Zend Framework   Zendcon09
Php Unit With Zend Framework Zendcon09
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
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
 

Viewers also liked (7)

77389 Home Sales Report - October 2015
77389 Home Sales Report - October 2015 77389 Home Sales Report - October 2015
77389 Home Sales Report - October 2015
 
June Homes Sales Report - The Woodlands TX | 2015
June Homes Sales Report - The Woodlands TX | 2015June Homes Sales Report - The Woodlands TX | 2015
June Homes Sales Report - The Woodlands TX | 2015
 
The Woodlands TX Home Sales Report - March | BHGRE Gary Greene
The Woodlands TX Home Sales Report - March | BHGRE Gary Greene The Woodlands TX Home Sales Report - March | BHGRE Gary Greene
The Woodlands TX Home Sales Report - March | BHGRE Gary Greene
 
The Spring (77386) Home Sales Report - November 2015
The Spring (77386)  Home Sales Report - November 2015 The Spring (77386)  Home Sales Report - November 2015
The Spring (77386) Home Sales Report - November 2015
 
Team Meeting Agenda Notes | Better Homes And Gardens Real Estate Gary Greene ...
Team Meeting Agenda Notes | Better Homes And Gardens Real Estate Gary Greene ...Team Meeting Agenda Notes | Better Homes And Gardens Real Estate Gary Greene ...
Team Meeting Agenda Notes | Better Homes And Gardens Real Estate Gary Greene ...
 
Tuesday Team Meeting Notes - October 25th, 2016
Tuesday Team Meeting Notes - October 25th, 2016Tuesday Team Meeting Notes - October 25th, 2016
Tuesday Team Meeting Notes - October 25th, 2016
 
February 2014 BHGRE Gary Greene Top Performers | The Woodlands and Magnolia M...
February 2014 BHGRE Gary Greene Top Performers | The Woodlands and Magnolia M...February 2014 BHGRE Gary Greene Top Performers | The Woodlands and Magnolia M...
February 2014 BHGRE Gary Greene Top Performers | The Woodlands and Magnolia M...
 

Similar to And the Greatest of These Is ... Rack Support

Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
Yehuda Katz
 
Integrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby AmfIntegrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby Amf
railsconf
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
danwrong
 

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

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
 
Adventurous Merb
Adventurous MerbAdventurous Merb
Adventurous Merb
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 
JavaScript on Rails 튜토리얼
JavaScript on Rails 튜토리얼JavaScript on Rails 튜토리얼
JavaScript on Rails 튜토리얼
 
Jsf Ajax
Jsf AjaxJsf Ajax
Jsf Ajax
 
Little Big Ruby
Little Big RubyLittle Big Ruby
Little Big Ruby
 
Integrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby AmfIntegrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby Amf
 
Flex With Rubyamf
Flex With RubyamfFlex With Rubyamf
Flex With Rubyamf
 
Application Layer in PHP
Application Layer in PHPApplication Layer in PHP
Application Layer in PHP
 
Rugalytics | Ruby Manor Nov 2008
Rugalytics | Ruby Manor Nov 2008Rugalytics | Ruby Manor Nov 2008
Rugalytics | Ruby Manor Nov 2008
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 

More from Ben 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
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
 
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
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
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
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
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
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
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
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
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
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 

And the Greatest of These Is ... Rack Support

  • 1. And the Greatest of These Is... Rack Support Ben Sco eld – Viget Labs
  • 3.
  • 7.
  • 8.
  • 10.
  • 11.
  • 12. def call(env) [ status, # 200 headers, # {quot;Content-Typequot; => quot;text/htmlquot;} body # [quot;<html>...</html>quot;] ] end
  • 13.
  • 15. request middleware application middleware response
  • 16.
  • 22.
  • 23.
  • 24.
  • 25. > rake middleware use Rack::Lock use ActionDispatch::Failsafe use ActionDispatch::ShowExceptions, [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
  • 26. > rake middleware use Rack::Lock use ActionDispatch::Failsafe use ActionDispatch::ShowExceptions, [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
  • 27. app = Rack::Builder.new { use Rails::Rack::LogTailer unless options[:detach] use Rails::Rack::Debugger if options[:debugger] map quot;/quot; do use Rails::Rack::Static run ActionController::Dispatcher.new end }.to_app
  • 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
  • 31.
  • 32. PLEASE testing metalBY STAND EXPAND: THIS IS ONLY A TEST
  • 36.
  • 37.
  • 38.
  • 39.
  • 44.
  • 45. class SessionsController < ApplicationController def create # ... session[:personalize] = { :logged_in => true, :quicklist => current_user.quicklist.episode_ids, :subscriptions => current_user.subscription_ids } end end
  • 46. class ChannelsController < ApplicationController caches_page :show def show @channel = Channel.find(params[:id]) end end
  • 47. $(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. }); });
  • 48. class Personalizer def self.call(env) if env[quot;PATH_INFOquot;] =~ /^/personalize/ [ 200, {quot;Content-Typequot; => quot;application/javascriptquot;}, env['rack.session'][:personalize].to_json ] else [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]] end end end
  • 49.
  • 50.
  • 51.
  • 52.
  • 53. class PullList def self.call(env) if env[quot;PATH_INFOquot;] =~ /^/pulls/ [ 200, {quot;Content-Typequot; => quot;application/javascriptquot;}, [Pull.by_user(user).for_date(date).map {|i| i.item_id}.to_json]] else [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]] end end end standard 0.617 progressive 0.039 0.096
  • 54. class PullList def self.call(env) if env[quot;PATH_INFOquot;] =~ /^/pulls/ [ 200, {quot;Content-Typequot; => quot;application/javascriptquot;}, [env['rack.session'][:pulls].to_json] ] else [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]] end end end standard 0.617 progressive 0.039 0.096 progressive v2 0.043 0.023
  • 55. DIY
  • 56. request middleware application middleware response
  • 58.
  • 59. class Embiggener < Test::Unit::TestCase def test_embiggener_should_embiggen_known_url body = [quot;Hello! I'm at http://tinyurl.com/cjmhvaquot;] assert_equal [quot;Hello! I'm at http://www.culann.comquot;], Rack:: Embiggener.embiggen_urls(body) end def test_embiggener_should_embiggen_multiple_urls body = [ quot;Hello! I'm at http://tinyurl.com/cjmhvaquot;, quot;And I'm at http://tinyurl.com/cjmhvaquot; ] assert_equal [ quot;Hello! I'm at http://www.culann.comquot;, quot;And I'm at http://www.culann.comquot; ], Rack::Embiggener.embiggen_urls(body) end end
  • 60. module Rack class Embiggener def self.embiggen_urls(original_body) new_body = [] original_body.each { |line| tinys = line.scan(/(http://(?:www.)?tinyurl.com/(.{6}))/) new_body << tinys.uniq.inject(line) do |body, tiny| original_tiny = tiny[0] preview_url = quot;http://preview.tinyurl.com/#{tiny[1]}quot; response = Net::HTTP.get_response(URI.parse(preview_url)) embiggened_url = response.body.match(/redirecturlquot; href=quot;(.*)quot;>/)[1] body.gsub(original_tiny, embiggened_url) end } new_body end # ... end end
  • 61. module Rack class Embiggener # ... def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) headers.delete('Content-Length') response = Rack::Response.new( Rack::Embiggener.embiggen_urls(body), status, headers ) response.finish return response.to_a end end end
  • 64. 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
  • 65.
  • 66. > rake middleware use Rack::Lock use ActionDispatch::Failsafe use ActionDispatch::ShowExceptions, [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
  • 67. Rails::Initializer.run do |config| # ... config.middleware.delete ActionDispatch::ShowExceptions config.middleware.delete ActionDispatch::Rescue config.middleware.use 'Rack::Hoptoad', 'my-hoptoad-api-key' config.middleware.use 'Rack::ShowExceptions' end
  • 68. 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
  • 69. module Rack class Hoptoad def notify_hoptoad(exception, env) headers = { 'Content-type' => 'application/x-yaml', 'Accept' => 'text/xml, application/xml' } url = URI.parse(quot;http://hoptoadapp.com/noticesquot;) http = Net::HTTP.new(url.host, url.port) data = { :api_key => @api_key, :error_message => quot;#{exception.class}: #{exception}quot;, :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
  • 70.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77. Thank You ben sco eld - @bsco eld - http://www.viget.com/extend - http://www.speakerrate.com/bsco eld

Editor's Notes

  1. Lots of awesome things coming to Rails
  2. standard API for all Ruby web frameworks
  3. ruby-prof, benchmark application
  4. replacement for exception notifier (but pay attention later)
  5. not in rack core ryan tomayko - earlier session?
  6. chain sinatra/merb/other rack apps file upload separate from main app
  7. script/server from railties/lib/commands/server.rb
  8. Rails version of Rack::Cascade
  9. talk about the poller example
  10. unit testing for the individual metal action integration testing for overall testing
  11. Adam Wiggins talked about this in his session yesterday
  12. 135ms for hybrid, which is 21% of the standard lame tests I employed showed the same or greater effect
  13. 66ms for hybrid v2, 10.6% of standard and 48% of hybrid
  14. cooperation - multiple people contributing to each other, like Double Dragon! this blonde guy is clearly in trouble, but if he had his buddy helping he&#x2019;d be golden