cre8cre8
AskMe♥

get,post,delete,putそしてmatchでルーティングを頑張る

RESTful原理主義者は見ちゃらめぇぇぇ…///
こんばんわ。たくみです。
今回は前回のresources,namespace,scopeだけで頑張るとは違う方法でルーティングを構築する方法を解説します。
Railsをたしなんでいる方はすでにお察しかもしれませんが、

を使用してルーティングしてきましょう。

それぞれのメソッドの役割

上記のメソッドはHTTPメソッドと対応しています。
HTTPメソッドには

のようにたくさん種類があります。
今回はGET,POST,DELETE,PATCHをつかいます。
タイトルに書いているmatchがない?
フフフ…matchさんは特別なヤツなので、最後に解説しますね。

get データの取得はおいどんにまかせるでごわす

getはHTTPメソッドでGETを飛ばすときに使用します。
主な用途としては、データを取得する処理 に使います。

config/routes.rb
1get 'anime/orenoyome', to: 'foos#index'

getメソッドの最初の引数 'anime/orenoyome' がURLパターンです。
後ろに続く to: 'foos#index' は 'コントローラ名#アクション名' です。
これでGETメソッドで localhost:3000/anime/orenoyome にアクセスすると
FoosControllerのindexメソッドが呼び出せるようになりましたね。
それでは、どんどん次にいきましょー

post 新たなデータを追加したい?フフフ…おまかせを…

postはその名の通り、HTTPメソッドでPOSTを飛ばすときに使用します。
主に情報の新規追加のときに使用しますが、ブラウザはGETとPOSTしか送れないので、
後述する消すときと更新するときにも使われることが多いです。(特に古めのWebアプリ)
そういうときは過去の遺産と思って割り切って対応するのが、幸せに過ごせる確率があがります。

config/routes.rb
1post 'moe/denpa/akiba', controller: 'foos', action: 'create'
2#
3# 上記の書き方は to: を使って下記のように書くこともできます。
4# post 'moe/denpa/akiba', to: 'foos#create'
5#

postの第一引数はgetと同様、URLを書きます。
今回は萌え!電波!アキバ!の気分だったので、 'moe/denpa/akiba' にしました。
第二、第三引数の controller: と action: ですが、
これは名前の通り、コントローラとアクションを指定します。
コメントにも書きましが、 to: を使えばタイプ数減りますので便利ですね。
controller:&action: か to: を使うかは好みになりますので、お好きなほうを使ってください。
これより下のサンプルコードでは、 to: を使って解説しますね。

delete なんでも消せるあたいってば天才ね

「なんでも消しちゃうあたいってば天才ね⑨」

deleteはDELETEメソッドを飛ばします。はい。この部分は説明しなくてももうわかりますね。
名前のとおり、情報を削除したいときに使います。
なのですが、ブラウザはこのHTTPメソッドをサポートしていません。
HTMLで、<form method="delete">...</form>としても、DELETEメソッドで飛ばないのです。
対応策としては、JavaScriptで無理やりDELETEメソッドにして飛ばすだったり、
クエリストリングのパラメータでdeleteとあったらDELETEメソッドとして扱うというようにしたり、
POSTで飛ばす際に<input type="hidden" name="method" value="delete">として対応したりします。

postのときの話の続きで、完全に余談ですが筆者はpostで削除されているところを
deleteで書き換えたら、ウェブアプリで削除できなくなったという不幸な経験がありますので、
すでにpostでdeleteの動きを実装されている場合は、触らぬ神に祟りなし、
そっとそのまま生暖かく見守りましょう。

config/routes.rb
1delete 'kurorekishi/:id', to: 'foo#delete'

なんと素晴らしい!黒歴史を削除してくれるようですw
URL指定の箇所の :id は controller の params[:id] で参照できるようになります。
だいたいは消すデータの主キー(id)を入れることが多いです。

patch 更新…したいの…?(幼女ボイス)

「ふぇぇ…更新しちゃうよぉ…」
ってな感じのときに使います。おじちゃん、元気になるぉ!( ^ω^)おっおっ!!

失礼しました。解説に戻ります。
patchは情報を更新するときに使います。SQLでいうと UPDATE するときですね。
もちろん、ブラウザはpatchなんてサポートしていませんので、deleteと一緒でなんらかの方法で対策します。
…が、deleteと異なり、ほとんどのウェブアプリでは POST で解決していると思います。
筆者の経験では、データの主キー、例えばidが一緒に送られてきたら更新して、それ以外は新規追加みたいな感じの実装が多いですね。
というか、それ以外は見たことないです。決して見たことあるけどショックで忘れたとかではないです。はい。

書き方は今までと同じです。

config/routes.rb
1patch 'death/flag/:id', to: 'foos#update'
指定したIDの死亡フラグを更新します。いろんな意味でワクテカするAPIですね(白目)
似たように更新を扱うメソッドで putメソッドがあります。
patchは一部を更新する時、putは全部を更新するときに使うようにきりわけます。

人類には早すぎた match

使い方しだいでは凶悪な使い方ができる matchメソッドです。
どれくらい凶悪かというと、 Rails3からRails4にバージョンアップしたときに
その挙動を変えられたくらい凶悪な代物です。
(ルーティング関係でVer3からVer4にできなかった場合はだいたいコイツのせいだと思われます。
そんな作り方をしている方が悪いと言われればそれまでですが…泣)
知識豊富ないいプログラマが使えば便利な代物なのですが、いかんせん悪いプログラマLv1とかが混じったプロジェクトだと
matchを使ったことにより事によりガバガバなルーティングができあがったりします。
では、そんな凶悪なmatchメソッドの使い方を解説しましょう!

config/routes.rb
1match 'foos/index', to: 'foos#index', via: 'get'

今までの例と同じで、第一引数はURLになります。
また、 controller:とaction: か to: を指定するかも一緒です。
最後の via: はHTTPメソッドの種類を決めます。

上記だけを見ると、get,post,delete,patch使うときよりviaが多いだけじゃん?なにが凶悪なの??
…いえいえ、matchの真の恐ろしさは to: および controller:,action: を省略できる ところにあるのです!
それでは禁断の黒魔術。最凶の凶悪な書き方をしたmatchを見てみましょう。

config/routes.rb
1match ':controller(/:action(/:id))', via: [:get, :post, :delete, :patch]

このmatchの意味はURLとHTTPメソッドに一致したコントローラ、アクションを呼び出します。
具体的なサンプルを箇条書きにしてみると下記のようになります。

get,post,patch,deleteを使って上記と同等のことをした場合は4行書かないといけませんが、
matchならたった1行ですんでしまいますね。シンプル最高!今度からmatchしか使わないぜ!

待ってください。便利さよりも恐ろしいものもあるのです。
もし、呼び出してほしくないアクションを記載していたり、削除したと思ったコントローラが残っていたりしたら…
具体的には顧客の秘密にしたい情報を扱うCustomerController#secretや、
アプリケーションのデバッグに使うDebugController#applicationを作っていた場合、
matchを使わないルーティングの設定の場合はroutes.rbに記載しない限りアクセスできませんが、
matchを書いていると...

でアクセスできちゃいます。またパスワードを変更するpasswordメソッド(アクションじゃないです。メソッドです。)を
CustomerControllerの中で定義していて、本来ならcreateアクションやupdateアクションの中から呼ばれる想定でいたのを、

でアクセスできちゃいます!もし、passwordが動いてしまったら…意図しないパスワードの書き換えが起こりますね。

まとめ

前回のRailsルーティングをresources/namespace/scopeで頑張ってみる
今回のget/post/delete/patchを使えばほとんどのルーティングを設計できると思います。
get/post/delete/patchを使えばRESTfulから外れたURLを設計できてしまう反面、
直感的かつシンプルにルーティングを表すことができます。
また、matchの危険性を認識した上でmatchを使いこなせるようになると、
より柔軟なURLを設計できるようになりますね。
条件にもよりますが、社内でしか使わない場合や1回しか使わないようなアプリの場合、
小難しく考えずにmatchを使ったほうが超短期で開発を終わらせることも可能になります。

以下は簡単なまとめになります。

おまけ

前回のRailsルーティングをresources/namespace/scopeで頑張ってみるで作った
resourcesをget/post/delete/patchで書き直すと以下のようになります。

config/routes.rb
1get 'worlds', to: 'worlds#index'
2post 'worlds', to: 'worlds#create'
3get 'worlds/new', to: 'worlds#new'
4get 'worlds/edit', to: 'worlds#edit'
5get 'worlds/:id', to: 'worlds#show'
6patch 'worlds/:id', to: 'worlds#update'
7put 'worlds/:id', to: 'worlds#update'
8delete 'worlds/:id', to: 'worlds#destroy'

長いですね…
RESTfulなURLを書くときには素直にresourcesを使ったほうが楽ですw
ちなみに、中の人はあまりget/post/delete/patchは使わず、
resources/namespace/scopeを使ってルーティングを作ることが多いです。

≪ 前の記事
RESTfulにするためRailsのルーティングをresources,namespace,scopeだけで頑張る
次の記事 ≫
getElementsByClassNameで指定したクラスを全部消す

いいねやコメントを送っていただけると中の人がしっぽ振って大喜びします♪

あなたへのおすすめの記事