在Ruby / Rails / Rack代码中使用“use”关键字/单词

时间:2012-08-16 07:11:05

标签: ruby-on-rails ruby rack rack-middleware

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

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

1 个答案:

答案 0 :(得分:27)

文档

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

  

<强> use(middleware, *args, &block)

     

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

This documentationpointed out by @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 source code不太熟悉,但看起来每次使用新的中间件模块调用use时,它都会被添加到数组中,并且每个模块都会运行/注入以相反的顺序添加它(后进先出顺序,也就是堆栈顺序)。运行上一个中间件的结果通过inject传递给堆栈中的下一个中间件:

  1. Lines 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. Lines 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. Lines 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
    
  4. 其他资源

    1. A Quick Introduction to Rack
    2. Ruby on Rack #2 - The Builder