如何将config.ru文件转换为单个Rack应用程序?

And*_*rew 9 ruby rack

我有一个config.ru文件,开始有重复的代码:

map '/route1' do
  run SampleApp.new
end

map '/route2' do
  run SampleApp.new
end
Run Code Online (Sandbox Code Playgroud)

我想将这个config.ru文件转换为自己的Rack应用程序,这样我所要做的就是:

map '/' do
  run MyApp.new
end
Run Code Online (Sandbox Code Playgroud)

创建自己的Rack应用程序的正确方法是什么?具体来说,我如何创建一个类,以便我可以map在我的类中使用该方法来定义一堆路由?


解:

这是一个有效的解决方案:

class MyApp

  def initialize
    @app = Rack::Builder.new do
      # copy contents of your config.ru into this block
      map '/route1' do
        run SampleApp.new
      end

      map '/route2' do
        run SampleApp.new
      end
    end
  end

  def call(env)
    @app.call(env)
  end
end
Run Code Online (Sandbox Code Playgroud)

我以前试过这个,但无法让它工作,因为我试图将实例变量传递给map块.例如:

def initialize
  @sample_app = SampleApp.new
  @app = Rack::Builder.new do
    map '/route1' do
      run @sample_app   # will not work
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这不起作用的原因是因为正在传递的块正在实例的上下文中map进行评估Rack::Builder.

但是,如果我传递一个局部变量,它将起作用:

def initialize
  sample_app = SampleApp.new
  @app = Rack::Builder.new do
    map '/route1' do
      run sample_app   # will work
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

mat*_*att 10

用于的DSL config.ru定义于Rack::Builder.使用a时config.ru,文件的内容将传递Builder给创建Rack应用程序的实例.您可以直接在代码中执行此操作.

例如,您可以获取现有内容config.ru,并从中创建一个新类:

require 'rack'

class MyApp

  def initialize
    @app = Rack::Builder.new do
      # copy contents of your config.ru into this block
      map '/route1' do
        run SampleApp.new
      end

      map '/route2' do
        run SampleApp.new
      end
    end
  end

  def call(env)
    @app.call(env)
  end
end
Run Code Online (Sandbox Code Playgroud)

您需要这种call方法,以便您的类是Rack应用程序,但您可以将请求转发到您创建的应用程序Builder.然后,您可以创建config.ru使用新应用的新功能:

require './my_app'

run MyApp.new
Run Code Online (Sandbox Code Playgroud)