- infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, env.inspect]}
- use Rack::CommonLogger
- use Rack::ShowExceptions
- map '/' do
- run infinity
- end
- map '/version' do
- map '/' do
- run Proc.new {|env| [200, {"Content-Type" => "text/html"}, "infinity 0.1"] }
- end
- map '/last' do
- run Proc.new {|env| [200, {"Content-Type" => "text/html"}, Rack::Request.new(env).params.inspect] }
- end
- end
執行先安裝rack gem install rack
使用 rackup -R infinity.ru -p 3000
其中map的寫法和routes.rb中做法差不多,回顧一下routes.rb中的寫法。
- ActionController::Routing::Routes.draw do |map|
- map.connect ':controller/:action/:id'
- end
routes.rb里面發生了什么呢?很不幸、里面過程錯綜復雜,橫跨了至少四個類Builder,Mapper,Route,RouteSet,我只能告訴你結果,一句map.connect生成了一個Route對象。
rack代碼則簡單的我可以輕易的討論。
- module Rack
- ...
- class Builder
- def initialize(&block)
- @ins = []
- instance_eval(&block) if block_given?
- end
- ...
- def map(path, &block)
- if @ins.last.kind_of? Hash
- @ins.last[path] = self.class.new(&block).to_app
- else
- @ins << {}
- map(path, &block)
- end
- end
- def to_app
- @ins[-1] = Rack::URLMap.new(@ins.last) if Hash === @ins.last
- inner_app = @ins.last
- @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) }
- end
- ...
- end
- end
- module Rack
- ...
- class URLMap
- def initialize(map)
- @mapping = map.map { |location, app|
- if location =~ %r{\Ahttps?://(.*?)(/.*)}
- host, location = $1, $2
- else
- host = nil
- end
- unless location[0] == ?/
- raise ArgumentError, "paths need to start with /"
- end
- location = location.chomp('/')
- [host, location, app]
- }.sort_by { |(h, l, a)| [-l.size, h.to_s.size] } # Longest path first
- end
- ...
- end
- end
注意[0...-1]是不包含-1這個元素的,所以to_app只執行了前兩句。map最終生成了一個url和Rack::URLMap對象的Hash。而在rails當中,url被切割成了多個segments。Rails這樣作也自有其用處,常見的redirect_to :action => 'action'就是這樣構造出url的,但是對于輕量級應用,就有一點大炮打蚊子了。
安徽新華電腦學校專業職業規劃師為你提供更多幫助【在線咨詢】