基本路由


config/routes.rb中的設定,決定了請求會由哪個控制器的動作處理,這邊要先來介紹Rails中典型路由(Regular route)與命令路由(Named route)設定的方式(注意,routes.rb中越前頭的設定會先套用)。

你可以設定整個應用程式的首頁,例如若想要在連結http://localhost:3000時,等同於連結http://localhost:3000/messages/index,可以如下:

root :to => 'messages#index'

Rails應用程式預設首頁是public/index.html,必須將之移除,才會讓以上設定有效,當然,記得在messages_controller.rb中建立index方法,並在app/views/messages中建立index.html.erb作為首頁回應。

如果要將某個網址請求分配至某個控制器的動作,可以使用match。例如:

match 'messages/show',   :to => 'messages#show',  :via => 'get'
match 'messages/update', :to => 'message#update', :via => [:get, :post]

以上可以簡化為以下:

match 'messages/show'   => 'messages#show', :via => 'get'
match 'messages/update' => 'message#update', :via => [:get, :post]

以上設定,相當於:

get  'messages/show'   => 'messages#show'
get  'messages/update' => 'messages#update'
post 'messages/update' => 'messages#update'

match有些設定省略時會有預設,例如:

match 'messages/show'  

相當於:

match 'messages/show'  => 'messages#show'

例如:

get 'messages/show'

相當於:

match 'messages/show' => 'messages#show', :via => 'get'

MVC 與 Rails 中,messages_controller.rb中的show若要取得id請求參數,必須使用messages/show/?id=1的請求方式,如果想在請求messages/show/1時,將id設為1,可以如下:
match 'messages/show/:id' => 'messages#show'

實際上,Rails會試著將請求網址匹配至每個:name,不過有些:name有意義,例如:controller與:action,來想想,應用程式中會有許多網址代表不同的請求動作,例如messages/create代表建立新訊息,messages/show/1代表顯示第一筆訊息、messages/update/1代表更新第一筆訊息,messages/destroy/1代表刪除第一筆訊息等,如果要逐一設定,會像是以下:
match 'messages/create'
match 'messages/show/:id' => 'messages#show' match 'messages/update/:id' => 'messages#update' match 'messages/destroy/:id' => 'messages#destroy'

也可以直接使用:controller、:action來指定控制器與動作:
match 'messages/:id' => :controller => 'messages', :action => show

如上設定之後,請求messages/1就會轉發給mesages_controller.rb中的show方法處理。

隨著應用程式越來越大,請求網址的匹配設定會越來越多,實在很麻煩,針對以上的設定,此時可以僅設定如下一行:
match ':controller(/:action(/:id(.:format)))'

其中括號表示網址請求中可有可無,事實上,這行正是在routes.rb中最後一行註解的內容,例如若請求messages/destroy/1,則:controller會是messages,:action會是destroy,:id會是1,而Rails會根據:controller與:action,自動將請求分配至messages#destroy,藉此簡化設定,不過要注意,這會讓所有控制器的每個公開動作,都可以使用GET請求,如果不想被請求的動作,請在方法上加上private限定。

現在假設你的routes.rb中有以下內容:
root :to => 'messages#index'
match ':controller(/:action(/:id(.:format)))'

假設你想在show.html.erb中加上個回首頁的鏈結,則可以如下:
  • show.html.erb
<ul>
    <li><%= @message.name %>'s message</li>
    <li><%= @message.content %></li>
</ul>
<%= link_to "Home", root_path %>

link_to是個輔助方法(Helper),會產生超鏈結語法,第一個參數是顯示的文件,第二個參數是實際的網址,在這邊使用root_path輔助方法來產生頁面的相對網址,如果使用root_url則會產生絕對網址。

實際上,有些match設定,都會產生*_path*_url的命名路由輔助方法,例如:
match 'messages/show'  

預設的命名路由就是messages_show、輔助方法就是messages_show_pathmessages_show_url。你也可以自行取名,例如:
match 'messages' => 'messages#index', :as => 'index'

則命名路由為index,而輔助方法為index_pathindex_url,你可以如下使用:

<%= link_to "Home",  index_path %>

如果是以下:

match 'messages/:id' => :controller => 'messages', :action => show, :as => messages

則可以如下使用輔助方法,其中message參考至Message實例:

<%= link_to "Show",  messages_path(message) %>

如果不使用命名路由的輔助方法,則可以在指定控制器與動作。例如:

<%= link_to "Home", :controller => 'messages', :action => 'index' %>

routes.rb中設定越前頭越先套用,*_url*_path輔助方法、網址與控制器動作的對應,可以執行rake routes指令來得知。

如果想限制參數,可以如下:
match "/messages/show/:id" => "messages#show", :constraints => {:id => /\d/}

這會限制id一定要是一個整數,也可以使用contraints方法作進階限定,例如限定IP位址:
constraints(:ip => /(^127.0.0.1\$)|(^192.168.[0-9]{1,3}.[0-9]{1,3}\$)/) do
   match "/admins/edit/:id" => "admins#edit"
end

Rails還支援RESTful路由設定,這在之後還會說明。