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オプションで引用することができる