20

最近碰巧在 Ruby 代码中看到了这个词use,当时我正在浏览一些与goliath、中间件等相关的代码。看起来它与include/extend和. 不同require

有人可以解释为什么这个use关键字存在,以及它与include/有何不同require?它是如何工作的,何时使用?

4

1 回答 1

33

文档

正如人们所指出的,use它不是 Ruby 关键字,它实际上是Rack::Builder的方法:

use(middleware, *args, &block)

指定要在堆栈中使用的中间件。

该文档由@user166390 指出)描述如下:

Rack::Builder实现了一个小的 DSL 来迭代地构建Rack应用程序。

例子:

app = Rack::Builder.new {
  use Rack::CommonLogger
  use Rack::ShowExceptions
  map "/lobster" do
    use Rack::Lint
    run Rack::Lobster.new
  end
}

或者

app = Rack::Builder.app do
  use Rack::CommonLogger
  lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'OK'] }
end

use将中间件添加到堆栈,run分派到应用程序。

源代码

我对Rack::Builder源代码不太熟悉,但是看起来每次您use使用新的中间件模块调用时,它都会被添加到数组中,并且每个模块都以添加的相反顺序运行/注入(最后-in-first-out order,又称堆栈顺序)。运行前一个中间件的结果通过以下方式传递给堆栈中的下一个中间件inject

  1. 第 53-56 行

    def initialize(default_app = nil,&block)
      # @use is parallel assigned to [].
      @use, @map, @run = [], nil, default_app
      instance_eval(&block) if block_given?
    end
    
  2. 第 81-87 行

    def use(middleware, *args, &block)
      if @map
        mapping, @map = @map, nil
        @use << proc { |app| generate_map app, mapping }
      end
      # The new middleware is added to the @use array.
      @use << proc { |app| middleware.new(app, *args, &block) }
    end
    
  3. 第 131-135 行

    def to_app
      app = @map ? generate_map(@run, @map) : @run
      fail "missing run or map statement" unless app
      # The middlewares are injected in reverse order.
      @use.reverse.inject(app) { |a,e| e[a] }
    end
    

其他资源

  1. 快速介绍机架
  2. Ruby on Rack #2 - 生成器
于 2014-03-07T08:42:12.793 回答