`
花花公子
  • 浏览: 130230 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

rack和actionpack的map对比

    博客分类:
  • ruby
阅读更多
简单的rackup配置
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的,但是对于轻量级应用,就有一点大炮打蚊子了。
3
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics