Rails 的 Route 會使用 match 方法來組成路徑
# Example matches
match ":controller/:action/:id", :via => :post
match "posts/ajax/:action", :controller => :posts
match "api/search/*rest", "api#search"
match "admin/login", "devise#new_session"
match "rack-intro", "pages#show", :defaults => { :id => 37 }
match "mini-rack/*args", my_rack_application
match "photos/:id", "photos#show",
:defaults => { :user_id => 37 },
:via => [ :get, :post],
:constraints => { :user_id => /^\d+$/ }
Route 會依照順序執行,找到第一個符合的條件,就會直接使用
假如 match 的第二個參數不是 hash ,通常都會接 controller#action 或者 Rack 的應用程式讓 Rails 呼叫
:arg => data 最後會集結成一個 hash
所以實際上有三個參數
分別是 rack-intro 、 controller#action 、 default 的 hash
Rails 中有些方法會跟 Ruby 的關鍵字相撞,Rails 採用半相容的方式來解決這個問題
接下來,我們會建立一個簡單的 match 方法,然後在裡面製作我們的 Router
# rainbow/lib/rainbow/routing.rb
module Rainbow
class RouteObject
def initialize
@rules = []
end
def match(url, *args)
end
def check_url(url)
end
end
# And now, Rainbow::Application:
class Application
def route(&block)
@route_obj ||= RouteObject.new
@route_obj.instance_eval(&block)
end
def get_rack_app(env)
raise "No routes!" unless @route_obj
@route_obj.check_url env["PATH_INFO"]
end
end
end
就像你看到的,這還不能做成一個路徑
RouteObject’s match() 跟 check_url() 裡面還是空的
我們來看一下 best_quotes 的設定
# best_quotes/config.ru
require "./config/application"
app = BestQuotes::Application.new
use Rack::ContentType
app.route do
match "", "quotes#index"
match "sub-app", proc { [200, {}, ["Hello, sub-app!"]] }
# 預設 routes
match ":controller/:id/:action"
match ":controller/:id",
:default => { "action" => "show" }
match ":controller",
:default => { "action" => "index" }
end
run app
這是 best_quotes 的 route 表
印出 config.ru 的 match(),會看到他呼叫了 Rainbow 的 RouteObject
如果 match 改 resource 或 root 方法,來設定路徑,就會跟 Rails 一樣了