Redmineから学ぶRuby on Railsの使い方【ルーティング】

Ruby on Railsチュートリアルでは、以下のようなシンプルな内容が紹介されています。

Rails.application.routes.draw do
    root ‘static_pages#home’
    get ‘static_pages/home’
    get ‘static_pages/help’
    get ‘static_pages/about’
end

現実的には、Scaffoldを使わず個別にModel, View, Controllerを作ることになります。routes.rbからルーティングの書き方を真似・・・参考にさせていただきます。

:asってなに?

root :to => 'welcome#index', :as => 'home'

:asオプションを使用すると、名前付きルーティングヘルパーを上書きして異なる名前を使用できます。

4.3 名前付きヘルパーをオーバーライドする

要は redirect_to や link_to で使う別名ですね。Viewで分かりやすいパスを付けるために使用する、と。

:viaってなに?

match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post]

matchメソッドと:viaオプションを使用することで、複数のHTTP動詞に同時にマッチするルーティングを作成できます。

3.7 HTTP動詞を制限する

get, post両方とも同じ処理をしたい場合は match で書くと1行で済むのでスリム。

:id => ?

match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'

動的セグメントのURLフォーマットを特定の形式に制限することができます。

3.8 セグメントを制限する

URLパラメータの書式を設定できる。constraintsを使わないほうが見やすいなぁ。

member

resources :journals, :only => [:edit, :update] do
    member do
        get ‘diff’
    end
end

以下のようなルーティングが生成される。

GET                /journals/:id/diff(.:format)
GET                /journals/:id/edit(.:format)
PATCH              /journals/:id(.:format)
PUT                /journals/:id(.:format)

resourcesにおけるupdateアクションはPATCH/PUT。:update については、/journals/:id/updateとはならない点に注意。(2.10.1 メンバールーティングを追加する

resources :users do
    resources :memberships, :controller => ‘principal_memberships’
    resources :email_addresses, :only => [:index, :create, :update, :destroy]
end

resourceの入れ子パターン。使うシーンが多そう。これについては、以下のようなルーティングが生成される。

GET                /users/:user_id/memberships(.:format)
POST               /users/:user_id/memberships(.:format)
GET                /users/:user_id/memberships/new(.:format)
GET                /users/:user_id/memberships/:id/edit(.:format)
GET                /users/:user_id/memberships/:id(.:format)
PATCH              /users/:user_id/memberships/:id(.:format)
PUT                /users/:user_id/memberships/:id(.:format)
DELETE             /users/:user_id/memberships/:id(.:format)

shallow

resources :projects do
    collection do
    get ‘autocomplete’
end

shallow do
    resources :memberships, :controller => ‘members’ do
        collection do
            get ‘autocomplete’
        end
    end
end

使う場面が多いと思われるが、やや複雑。親のスコープの下でもURLを作りたい時に使用する。(2.7.2 「浅い」ネスト

以下のようなルーティングが(ry

GET                /projects/:project_id/memberships/autocomplete(.:format)
GET                /projects/:project_id/memberships(.:format)
POST               /projects/:project_id/memberships(.:format)
GET                /projects/:project_id/memberships/new(.:format)
GET                /memberships/:id/edit(.:format)
GET                /memberships/:id(.:format)
PATCH              /memberships/:id(.:format)
PUT                /memberships/:id(.:format)
DELETE             /memberships/:id(.:format)

collection

resources :trackers, :except => :show do
    collection do
        match ‘fields’, :via => [:get, :post]
    end
end

これはmemberのパラメータが無いバージョンか。(2.10.2 コレクションルーティングを追加する

GET|POST           /trackers/fields(.:format)

な、なにこれぇ

Dir.glob File.expand_path(“#{Redmine::Plugin.directory}/*”) do |plugin_dir|
    file = File.join(plugin_dir, “config/routes.rb”)
    if File.exists?(file)
        begin
            instance_eval File.read(file)
        rescue Exception => e
            puts “An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}.”
            exit 1
        end
    end
end

あ! プラグイン用のルーティングを読み込むロジックのようです。こんな風に書けるんですね。

思ったこと

struts configやApache, Nginxのルーティング地獄絵図に何度か遭遇したことがありますが、迷路にならないように心がける必要があります。その点、Redmineのルーティング設定はシンプルで素敵でした。Railsだけで完結できると幸せになれそうです。

新規でWebサイトを作る場合は、サイト構造を決めてからルーティングのひな形を作成するとスムーズになるんじゃないかなと思います。