12. Problems
⢠Ruby is popular
⢠Different web servers (app servers)
⢠Different web frameworks
⢠each framework has to write itâs own
handlers to different web servers
⢠Not only the handler
29. module Rack
class BeijingOnRails
def initialize(app)
@app = app
end
def call(env)
... ...
status, headers body = @app.call(env)
... ...
[status, header, body]
end
end
end
34. Rack - SpeciďŹcation
⢠Rack::Lint
specify "notices status errors" do
lambda {
Rack::Lint.new(lambda { |env|
["cc", {}, ""]
}).call(env({}))
}.should.raise(Rack::Lint::LintError).
message.should.match(/must be >=100 seen as integer/)
lambda {
Rack::Lint.new(lambda { |env|
[42, {}, ""]
}).call(env({}))
}.should.raise(Rack::Lint::LintError).
message.should.match(/must be >=100 seen as integer/)
end
38. Rack - Utilities
⢠Rackup
⢠a useful tool for running Rack
applications
⢠Rackup::Builder
⢠DSL to conďŹgure middleware and build
up applications easily
39. app = Rack::Builder.new do
use Rack::CommonLogger
use Rack::ShowExceptions
use Rack::ShowStatus
use Rack::Lint
run MyRackApp.new
end
Rack::Handler::Mongrel.run app, :Port => 8080
44. 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
46. Metal
⢠bypass some of the normal overhead of the
Rails stack
⢠specify certain routes and code to execute
when those routes are hit.
⢠avoid the entirety of ActionController
⢠Rails::Rack::Metal
⢠ActionController::MiddlewareStack
47. $ script/generate metal poller
class Poller
def self.call(env)
if env["PATH_INFO"] =~ /^/poller/
[200, {"Content-Type" => "text/html"},
["Hello, World!"]]
else
[404, {"Content-Type" => "text/html"},
["Not Found"]]
end
end
end
48. Rack::Metal
def call(env)
@metals.keys.each do |app|
result = app.call(env)
return result unless result[0].to_i ==
404
end
@app.call(env)
end
50. module Rack
class Runtime
def initialize(app, name = nil)
@app = app
@header_name = "X-Runtime"
@header_name << "-#{name}" if name
end
def call(env)
start_time = Time.now
status, headers, body = @app.call(env)
request_time = Time.now - start_time
if !headers.has_key?(@header_name)
headers[@header_name] = "%0.6f" % request_time
end
[status, headers, body]
end
end
end
56. Q &A
⢠Rack
⢠Ruby on Rails
⢠Caibangzi.com
⢠Mutual Fund & Investment
57. Why not simply string
⢠Ruby 1.8
⢠String was a collection of bytes
⢠Stringâs :each method iterated over lines of data
⢠Ruby 1.9
⢠String is now a collection of encoded data. (Raw
bytes and encoding information)
⢠:each has been removed from String and itâs no
longer Enumerable