Intro to Rack
Upcoming SlideShare
Loading in...5
×
 

Intro to Rack

on

  • 3,823 views

 

Statistics

Views

Total Views
3,823
Views on SlideShare
3,823
Embed Views
0

Actions

Likes
0
Downloads
34
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Intro to Rack Intro to Rack Document Transcript

  • Your best friend Rack
  • What is Rack? Rack provides a minimal interface“ between webservers supporting Ruby and Ruby frameworks.Transparently integrates in your existing rails, sinatra apps Helps you easily create a middleware standalone application stack
  • Yeah! but... what is Rack? A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment and returns an Array of exactly threevalues: The status, the headers, and the body.
  • A basic Rack app diagram
  • Minimum server interface you said?app = lambda d o |env| [200, { Content-Type => text/html Hello World]endrun app
  • Where does Rack sit?
  • Rack is a fullmiddleware stack
  • Allows a modular design
  • What is a middleware? Rack application that is designed“ to run in conjunction with another Rack application, which acts as the endpoint
  • ... Think of a Rack middleware as a filterreceiving the Rack environment for therequest from the previous middleware Does some work with or on the requests environmentThen calls the next middleware in the chain
  • ... The last Rack application in the“ chain is the application itself Any middleware in the chain canreturn the Rack response itself, thuspreventing the rest of the middlewares in the chain from executing
  • Installation$... $ gem install rackSuccessfully installed rack-1.2.11 gem installedInstalling ri documentation for rack-1.2.1...Building YARD (yri) index for rack-1.2.1...Installing RDoc documentation for rack-1.2.1...
  • Lets talk more Rackstatus, headers, body = object[200, { Content-Type => text/html } Hello World]
  • Stacking appsm o d u l e MyModule c l a s s Upcase d e f initialize app @app = app end d e f call env p upcase status, headers, body = [status, headers, [body. end endend
  • ...m o d u l e MyModule c l a s s Reverse d e f initialize app @app = app end d e f call env p reverse status, headers, body = [status, headers, [body. end endend
  • ...use MyModule::Upcaseuse MyModule::Reverseuse Rack::ContentLengthapp = lambda { |env| [200, { Contentrun app
  • ...$...$ rackup stacked1.ru &[1] 2123...$ curl localhost:9292"upcase""reverse"127.0.0.1 - - [03/Nov/2010 16:15:34] "GET / HTTP/DLROW OLLEH...$
  • What happened?A Decorator pattern happens In OOP, the decorator pattern is“ a design pattern that allows new/additional behaviour to be added to an existing object dynamically
  • Basic APIuse(middleware, **args, &block) adds a middleware to the stack run(app) dispatches to an application map(path, &block) constructs a Rack::URLMap in a convenient way
  • Basic API - usage exampler e q u i r e rack-validateuse Rack::Validatemap /hello d o run lambda d o |env| [200, { Content-Type => text/html Hello World] endend
  • Rake::Validate fromhttp://coderack.org/
  • Basic optional usage - Rack::BuilderProvides an optional DSLapp = Rack::Builder.new d o map "/hello" d o run lambda d o |env| [200, { Content-Type => text/html Hello World] end endend
  • Rack convenience Wanna develop outside of existing frameworks, implement your own ones, or develop middleware?Rack provides many helpers to createRack applications quickly and without doing the same web stuff all over
  • Rack::Requestreq = Rack::Request.new(env)req.post?req.params["data"]
  • Rack::Responseres = Response.newres.write "<title>Lobstericious!</title>"res.write "<pre>"res.write lobsterres.write "</pre>"res.write "<p><a href=#{href}>flip!</a>res.write "<p><a href=?flip=crash>crashres.finish
  • use Rack::CommonLoggerWrites a log statement to STDOUT in the Apache common log format for each request use Rack::ShowExceptions Renders a nice looking errors page for all unhandled exceptions use Rack::Lint Ensures that your Rack application conforms to the Rack spec. Rack::Lint will generate anexception if the response of your application does not meet the Rack spec
  • And many more Rack::Auth::Basic Rack::Session::Cookie Rack::Sendfile http://coderack.org/http://rack.rubyforge.org/doc/
  • Is this testable? Use your favorite frameworkIt provides Rack::MockRequest and Rack::MockResponse
  • With bacon Bacon is a small RSpec clone“ weighing less than 350 LoC but nevertheless providing all essential features.
  • MockRequestdescribe Rack::Static d o root = File.expand_path(File.dirname(_ _ F I L E _ _ _ OPTIONS = {:urls => ["/cgi"], :root => root @request = Rack::MockRequest.new( Rack::Static.new(DummyApp.new, OPTIONS it "serves files" d o res = @request.get("/cgi/test") res.should.be.ok res.body.should =~ /ruby/ endend
  • MockResponsedescribe Rack::Chunked d o before d o @env = Rack::MockRequest. env_for(/, HTTP_VERSION => 1.1, REQUEST_METH end should chunk responses with no Content-Length d o app = lambda { |env| [200, {}, [Hello, response = Rack::MockResponse.new( *Rack::Chunked.new(app).call(@env)) response.headers.should.n o t .i n c l u d e Content-Le n i response.headers[Transfer-Encoding].should response.body.should.equal "5rnHellorn1rn rn6rnWorld!rn0rnrn" endend
  • Why do we care? Supported web servers Mongrel, EventedMongrel, SwiftipliedMongrelWEBrick, FCGI, CGI, SCGI, LiteSpeed Thin
  • These web servers includehandlers in their distributions Ebb, Fuzed, Glassfish v3 Phusion Passenger (which is mod_rack for Apache and for nginx) Rainbows!, Unicorn, Zbatery
  • Any valid Rack app will runthe same on all these handlers, without changing anything
  • Supported web frameworksCamping, Coset, Halcyon, Mack Maveric, Merb, Racktools::SimpleApplication Ramaze, Rum, Sinatra, Sin Vintage, Waves Wee, … and many others.
  • Of course Ruby on RailsRails has adopted the Rack philosophy throughout the framework A Rails application is actually a collection of Rack and Rails middleware components that all work together to form the completed whole
  • Listing the rails middleware stack$...(master) $ rake middleware(in /home/chischaschos/Projects/salary-manager)use ActionDispatch::Staticuse Rack::Lockuse ActiveSupport::Cache::Strategy::LocalCacheuse Rack::Runtimeuse Rails::Rack::Loggeruse ActionDispatch::ShowExceptionsuse ActionDispatch::RemoteIpuse Rack::Sendfileuse ActionDispatch::Callbacksuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacheuse ActionDispatch::Cookiesuse ActionDispatch::Session::CookieStoreuse ActionDispatch::Flashuse ActionDispatch::ParamsParseruse Rack::MethodOverrideuse ActionDispatch::Headuse ActionDispatch::BestStandardsSupportuse Warden::Manageruse Sass::Plugin::Rackrun SalaryManager::Application.routes
  • Things to note The Rack application being run withthe run directive at the end of the list of middlewares is the Rails applications routes
  • Rails controllers are rack compliant A controller declarationc l a s s HomeController < ApplicationCont d e f index render :text => "Im your home cont endend
  • Rails console testing (had to shorten the output)$ruby-1.8.7-p302 > ...$ rails consoleLoading development environment (Rails 3.0.0)ruby-1.8.7-p302 > app = RailsRackApp::Applicationruby-1.8.7-p302 > app.class => ActionDispatch::Routing::RouteSetruby-1.8.7-p302 > env = {REQUEST_METHOD => GET => {"PATH_INFO"=>"/home/index", "REQUEST_METHOD"ruby-1.8.7-p302 > status, headers, body = app.cal => [200, {"ETag"=>""d47cb2eec6f22cb9ff6fbb21cd3ruby-1.8.7-p302 > body.body => "Im yout home controllers body"
  • Rack app from a controller declaration$ruby-1.8.7-p302 > app = HomeController.action :i => #<Proc:0xb6e26664@/home/chischaschos/.rvm/gemruby-1.8.7-p302 > app.respond_to? call => trueruby-1.8.7-p302 > status, headers, body = app.cal=> [200, {"ETag"=>""d47cb2eec6f22cb9ff6fbb21cd34ruby-1.8.7-p302 > body.body => "Im yout home controllers body"
  • There are two different ways to install Rack components into your Rails application 1 - Either configure your Rack application as part of your applications middleware stack 2 - Or you can route URI paths directly to the Rack application from you applications routes
  • 1.1 - Installing a component into your application lib/average_time.rb c l a s s AverageRuntime @@requests = 0 @@total_runtime = 0.0 d e f initialize(app) @app = app end d e f call(env) code, headers, body = @app.call(env @@requests += 1 @@total_runtime += headers[X-Runtime headers[X-AverageRuntime] = (@@total_runtime / @@requests).to_s [code, headers, body] end
  • 1.2 - Inserting the middleware config/application.rbr e q u i r e File.expand_path(../boot, _ _ F I L E _ _r e q u i r e rails/allBundler.r e q u i r e (:default, Rails.env) rm o d u l e RailsRackApp c l a s s Application < Rails::Application # starts the important part config.autoload_paths += %W(#{config config.middleware.insert_before Rack "AverageRuntime" # end the important part config.encoding = "utf-8" config.filter_parameters += [:password endend
  • 1.3 - Verifying middleware is in the stack$...$ rake middleware(in /home/chischaschos/Projects/rack-testing/rails-rack-app)use ActionDispatch::Staticuse Rack::Lockuse AverageRuntimeuse ActiveSupport::Cache::Strategy::LocalCacheuse Rack::Runtimeuse Rails::Rack::Loggeruse ActionDispatch::ShowExceptionsuse ActionDispatch::RemoteIpuse Rack::Sendfileuse ActionDispatch::Callbacksuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacheuse ActionDispatch::Cookiesuse ActionDispatch::Session::CookieStoreuse ActionDispatch::Flashuse ActionDispatch::ParamsParseruse Rack::MethodOverrideuse ActionDispatch::Headuse ActionDispatch::BestStandardsSupportrun RailsRackApp::Application.routes
  • 1.4 Testing our middlewareLook at X-Averageruntime: header $...$ curl -I localhost:3000 HTTP/1.1 404 Not Found Connection: Keep-Alive Content-Type: text/html Date: Fri, 05 Nov 2010 16:04:43 GMT Server: WEBrick/1.3.1 (Ruby/1.8.7/2010-08-16) X-Runtime: 0.312526 Content-Length: 621 X-Averageruntime: 0.312526
  • 2.1 - Routing to a rack application lib/walking_arrow.rbc l a s s WalkingArrow ARROW = => @@spaces = 0 d e f call(env) @@spaces += 1 [200, {Content-Type => text/plain}, endend
  • 2.2 - Add a route lib/walking_arrow.rbr e q u i r e lib/walking_arrow.rbRailsRackApp::Application.routes.draw get home/index get walkingarrow => WalkingArrow.newend
  • 2.3 Testing our middleware Walk!!!$...$ curl localhost:3000/walkingarrow =>...$ curl localhost:3000/walkingarrow =>...$ curl localhost:3000/walkingarrow =>...$ curl localhost:3000/walkingarrow =>...$ curl localhost:3000/walkingarrow =>...$ curl localhost:3000/walkingarrow =>
  • Before diving into rack and rails creation Learn and play with some examples http://guides.rubyonrails.org /railsonrack.html
  • Do you have ideas on how to use it?
  • Most sincere thanks to http://rack.rubyforge.org/doc/ http://rails-nutshell.labs.oreilly.com /ch07.htmlhttp://rubylearning.com/blog/2010/09/21 /writing-modular-web-applications- with-rack/?utmsource=twitterfeed& utmmedium=twitter And Mendo
  • Referencesgithub repo and examples chischaschos twitter