Rails Wayを読む(4)

4. REST、リソース、Rais

RailsがRESTをサポートしたことにより、アクション名の標準化がなされました。これにより、規約に則って開発してる分にはすごく楽チンだよ、ということみたいです。
標準のアクションとして、(index、create、show、update、destroy、new、edit)が提供されます。そのルーティングルールは

  map.resources :hoges

だけでおしまい。すっきりしてます。さらにURLの生成の方は、リソース名をもとにしたメソッドが自動的に生成されます(前章の名前つきルートを使ってるんでしょうかね)

  new_hoge_path
  hoge_path(@hoge)
  edit_hoge_path(@hoge)
  hoges_path

単・複数系の名前を使い分けて4つのメソッドが作られます。これだけだと7つのアクションに結びつけることができないのですが、HTTPのリクエストメソッドと組み合わせることで7つのアクションに振り分けられてしまうのです。書き方は間違ってますが、こんなイメージです。

  # /hoges/1
  get: hoge_path(@hoge) # => show
  # /hoges/1
  put: hoge_path(@hoge) # => update
  # /hoges/1
  delete: hoge_path(@hoge) # => delete
  # /hoges
  get: hoges_path # => index
  # /hoges
  post: hoges_path # => create
  # /hoges/1/edit
  get: edit_hoge_path(@hoge) # => edit
  # /hoges/1/new
  get: new_hoge_path # => new

editとnewだけ変なのがくっついていますが、「新規作成フォーム」「編集フォーム」というリソースと考えると納得できそうです。
ちなみに、現在のWebブラウザはGET, POST以外のメソッドをサポートしていなかったりするので、隠しフィールドにメソッド名を仕込んでリクエストを投げることにより、Railsがうまいこと解釈してくれるようです。こんな感じでしょうか。

  <input type="hidden" name="_method" value="delete" />

よくある掲示板とかだと、確認画面がありますが、/hoges/1/previewとかあってもいいような気がします。こんな感じで標準化されたアクションにアクションメソッドを追加できます。

  # リクエストメソッドのところは、:getだけじゃなく:any(なんでも)も使えます
  map.resources :hoges, :member => { :preview => :get }

どんどん追加していくことができますが、標準化という意味ではどんどん:memberを追加していくようなことになったときは設計がおかしいんじゃね、と思うべきとのこと。
単数形リソースなんてのもあります。が省略。
ネストしたリソースを表現することもできます。

  # こんなルーティングルール
  map.resources :hoges do |hoge|
    hoge.resources :fugas
  end

  # こんなURL生成メソッド(すごい)
  hoge_fugas_path(@hoge)
  hoge_fuga_path(@hoge, @fuga)
  ...

何階層でもいけますが、これもわかりやすさとかを考慮してあんまり深くしすぎない方が良いですよ。

Rails Way (Professional Ruby Series)

Rails Way (Professional Ruby Series)

追記

ちょっと勘違いしてました。
リソースに対してアクションを追加する場合、:member/:collection/:newを使い分けなければなりません。

map.resources :messages, :collection => { :rss => :get }
# --> GET /messages/rss (#rssアクションにマップします)
# "rss_messages"と呼ばれる名前付きルートも追加します

map.resources :messages, :member => { :mark => :post }
# --> POST /messages/1/mark (#markアクションにマップします)
# "mark_message"と呼ばれる名前付きルートも追加します

map.resources :messages, :new => { :preview => :post }
# --> POST /messages/new/preview (#previewアクションにマップします)
# "preview_new_message"と呼ばれる名前付きルートも追加します

map.resources :messages, :new => { :new => :any, :preview => :post }
# --> POST /messages/new/preview (#previewアクションにマップします)
# "preview_new_message"と呼ばれる名前付きルートも追加します
# --> どんなメソッドのリクエストでも、/messages/newを呼び出すことができます

http://www.eisbahn.jp/yoichiro/Resources.html

ついでに、ほかにもオプションがいろいろあるので引用元ページをいっかいちゃんと読もうと思います!