寝て起きて寝て

プログラミングが出来ない情報系のブログ

Railsのルーティング(3)~RESTfulのカスタマイズ~

前回の続き

RESTfulインターフェイスに自前のアクションを追加

collection/memberブロックを利用することで自前のアクションを増やすことができる。 ただし、あまりにも多くのアクションを追加したい場合は別に作るべき。設計し直そう

構文は以下のとおり

resources :name do
  [collection do
   method action
   ・・・・・・・
   end]
  [member do
   method action
   ・・・・・・・
  end]
end

nameはメソッド名 method は関連つけるHTTPメソッド(put,get,postとか) action は関連つけるアクション

例: reviewsリソースに関するルート定義にunapprovalアクションとdraftアクションを追加する例

routes.rb

resource :reviews do
  collection do
    get :unapproval
  end
  member do
    get :draft
  end
end

unapprovalアクションは複数オブジェクト draftアクションは単一オブジェクトで追加されている

これを実行すると以下の様なルート定義になる

ブロック URLパターン URLヘルパー
collection /reviews/unapproval(.:format) unapproval_reviews_path,unapproval_reviews_url
member /reviews/:id/draft(.:format) draft_review_path,draft_review_url

ブロック配下のアクションが一つである場合はonを使ってシンプルに書くこともできる

resources :reviews do
  get :unapproval,on: :collection
  get :draft, on: :member

RESTfulインターフェイスのアクションを無効化する

デフォルトで生成されるアクションの一部を無効化したいという場合にはonry/exceptオプションを指定する。

これはルート定義が複雑になった場合、不要なルートを残しておくことはパフォーマンスの低下させる原因になる。 よって使わないことがわかっている場合は必ず無効化しておく

無効化するにはexceptを使用する

例: routes.rb

resources :users,except: [:show, :destroy]

これでshowとdestroyのアクションを無効化することができた

また指定したアクションだけをルート定義させたい場合はonryを使う

resources :users, only: [:index, :new, :create, :edit, :update]

階層構造を持ったリソースを表現する

これはアプリケーションの中でリソース同士が親子関係にあるとする 例 booksには書籍情報がある(親) reviewsには書籍レビューがある(子) など こうしたリソース同士の関係はURLとしても表現ができたほうがわかりやすい。 例 books/1/reviews モデル名/id/reviews

ではどうやってやるかというと

resources :books do
  resources :reviews
end

で表現することができる これを実行すると /books/book_id/reviews というようにネストされている形になる 注目すべきところはidがbook_idになっているところ URLヘルパーには接頭辞「book_」が付与され直感的にわかりやすくなっている

メソッドのネストはいくらでもすることができるが、原則として2階層までにしておいたほうがいい。(わかりにくくなるため)

リソースの浅いネストを表現

ネストをするとURLが不用意に長くなる可能性がある id=10の書籍かつその書籍のid=8のレビューを表示させたい場合

/books/10/reviews/8

となってしまう

レビューのid値が書籍のidによらず一意であるなら

/reviews/8 と表せたほうがいい

これをするためにshallowオプションが有る

resources :books do
  resources :reviews,shallow:true
end

これを実行すると:idパラメータを受け取らないindex,new,createアクションでのみ :book_idパラメータが付与され、それ以外のアクションではネストされない。

ルート定義を再利用可能にする

同じルート定義をするのはとても面倒くさいので一度設定しそこから引っ張り出せるようにする

resources :reviews do
  get :unapproval, on: :collection
  get :draft, on: :member
end

resources :users do
  get :unapproval, on: :collection
  get :draft, on: :member
end

ここではルート定義が全く同じになっている これは無駄な作業なので定義し引用してきたい

resources :additional do
  get :unapproval, on: :collection
  get :draft, on: :member
end

resources :reviews,concerns: :additional
resources :users,concerns: :additional

concernオプションで引用することができる