Your SlideShare is downloading. ×
And the Greatest of These Is ... Rack Support
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

And the Greatest of These Is ... Rack Support

3,177
views

Published on

Presentation given at Railsconf 2009, about Rack support in Rails and the possibilities it presents.

Presentation given at Railsconf 2009, about Rack support in Rails and the possibilities it presents.

Published in: Technology, Design

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,177
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
32
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide


  • Lots of awesome things coming to Rails








  • standard API for all Ruby web frameworks



  • ruby-prof, benchmark application
  • replacement for exception notifier (but pay attention later)
  • not in rack core
    ryan tomayko - earlier session?
  • chain sinatra/merb/other rack apps
    file upload separate from main app





  • script/server
    from railties/lib/commands/server.rb

  • Rails version of Rack::Cascade

  • talk about the poller example
  • unit testing for the individual metal action
    integration testing for overall testing
  • Adam Wiggins talked about this in his session yesterday

















  • 135ms for hybrid, which is 21% of the standard

    lame tests I employed showed the same or greater effect
  • 66ms for hybrid v2, 10.6% of standard and 48% of hybrid




















  • 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’d be golden

  • Transcript

    • 1. And the Greatest of These Is... Rack Support Ben Sco eld – Viget Labs
    • 2. #?forben
    • 3. Application Templates
    • 4. Nested Attribute Assignment ickr: angelrays
    • 5. ActiveRecord::Base#touch ickr: jjjohn
    • 6. Rack
    • 7. def call(env) [ status, # 200 headers, # {quot;Content-Typequot; => quot;text/htmlquot;} body # [quot;<html>...</html>quot;] ] end
    • 8. request application response
    • 9. request middleware application middleware response
    • 10. Rack::Pro ler ickr: oberazzi
    • 11. Rack::MailExceptions ickr: warmnfuzzy
    • 12. Rack::Cache ickr: timpatterson
    • 13. rack::cascade Rack::Cascade ickr: _at
    • 14. Rack in Rails
    • 15. > 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
    • 16. > 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
    • 17. 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
    • 18. 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
    • 19. Metal ickr: lrargerich
    • 20. http://www.kiwibean.com/
    • 21. PLEASE testing metalBY STAND EXPAND: THIS IS ONLY A TEST
    • 22. METAL Sinatra
    • 23. Cool Tricks
    • 24. Rack::Bug ickr: catdancing
    • 25. requires </body>
    • 26. Progressive Caching
    • 27. Progressive Caching
    • 28. Progressive Caching
    • 29. class SessionsController < ApplicationController def create # ... session[:personalize] = { :logged_in => true, :quicklist => current_user.quicklist.episode_ids, :subscriptions => current_user.subscription_ids } end end
    • 30. class ChannelsController < ApplicationController caches_page :show def show @channel = Channel.find(params[:id]) end end
    • 31. $(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. }); });
    • 32. 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
    • 33. 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
    • 34. 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
    • 35. DIY
    • 36. request middleware application middleware response
    • 37. Rack::Embiggener
    • 38. 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
    • 39. 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
    • 40. 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
    • 41. WARNING exception handling
    • 42. formerly: WARNING exception handling
    • 43. 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
    • 44. > 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
    • 45. 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
    • 46. 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
    • 47. 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
    • 48. Intangibles
    • 49. Thank You ben sco eld - @bsco eld - http://www.viget.com/extend - http://www.speakerrate.com/bsco eld