Base

常用方法:

match

mount

root

match 方法

这里的 match 只是个同名方法,是个空壳子,具体实现要看 Resources 里的 match.

另外,mount 和 root 本质上,都是封装和扩展 match 方法。

mount 和 root
      |
      V
    match

mount 方法

挂载一个基于 Rack 的应用到我们的程序。

match '/movies/search', => "movies#search"
# 去掉语法糖,等价
match '/movies/search', => MoviesController.action(:search)
# 这是一个 Rack. 所以可以调用 call 方法,传递 env 对象。
MoviesController.action(:search).call(env)

# 这也是一个 Rack.
Proc.new { |env|
  [
    200,
    {"Content-Type" => 'text/plain'},
    ["Hello, world"]
  ]
}

# 这还是一个 Rack.
class ApiApp
  def call(env)
    [
      200,
      {"Content-Type" => 'text/plain'},
      ["Hello, world"]
    ]
  end
end
# 替换 Rack
match '/movies/search', => proc { |env|
                                  [
                                    200,
                                    {"Content-Type" => 'text/plain'},
                                    ["Hello, world"]
                                  ]
                                }
# 替换 Rack
match '/movies/search', => ApiApp
# 进价
scope '/api' do
  match '(*path)', => ApiApp
end

# 加上语法糖,等价
mount ApiApp, :at => '/api'
# 或
mount ApiApp => "api"

因为 mount 实现基于 match,可以使用相同的可选参数。例如:

mount(SomeRackApp => "some_route", as: "exciting")

现在,你可以通过 exciting_pathexciting_url 访问到刚才挂载的应用。

使用 mount 代替match 还有一个细节不同,在被挂载的 Rack endpoint 里,映射路由时我们不必加前缀。举例:

不是:

require 'sinatra'
class ApiApp < Sinatra::Base
  get '/api' do
  end

  get "/api/endpoint" do
  end

  post "/api/endpoint" do
  end
end

而是:

require 'sinatra'
class ApiApp < Sinatra::Base
  get '/' do
  end

  get "/endpoint" do
  end

  post "/endpoint" do
  end
end

root 方法

实现:

def root(options = {})
  match '/', { :as => :root, :via => :get }.merge!(options)
end

因为 root 实现基于 match,可以使用相同的可选参数。

建议你把 root 放在 config/routes.rb 的开头部分,因为 Rails 的匹配规则是从上至下生成的,会优先匹配。

最后更新于