SinatraでHTTPメソッドのDELETEを実現する
SinatraでHTTPメソッドのDELETEを実装する時かなりはまったのでメモです。実はもっと賢いやり方があるのかもしれないので、コメント大歓迎(基本的に僕のブログは全部そうです)。
今回は間違ったところから書きました。
使用環境
- ruby : 1.9.3-p286
- sinatra : 1.3.3
- haml : 3.1.7
- rspec : 2.11.0
- capybara : 1.1.3
- capybara-webkit : 0.13.0
です。
関係しそうなもの
Sinatraのルーティング
SinatraのreadmeのRoutesの中で get、post、put、patch、delete、optionsが指定できますっぽいことが書かれています。
Sinatraの設定で関係あるもの
SinatraのreadmeのConfigration ではmethod_overrideオプションの説明があります。この記述で、「ブラウザーがDELETEメソッドとかPUTメソッドをサポートしない場合、この設定が必要になる」っぽいことが書かれています。これを読んだ時に、「まさか最新のブラウザーがDELETEメソッドとかサポートしてないはずないだろうー」と思ったのが間違いだった。
間違ったコード
上記の調べたものから「DELETEメソッドなんて新しいブラウザがサポートしてるに決まってる」と間違った解釈をして書いたコードがこちら。
hoge.rb
class HogeApp < Sinatra::Base get "/" do # Hogeの一覧を取得 end delete "/destroy_hoge/:number" do # Hogeの削除処理 end end
index.haml
#... %a{href: "/destroy_hoge/#{hoge.number}", 'data-method' => 'delete', rel: 'nofollow' } Destroy
この場合テストは通るけどブラウザで実際動かすとエラーになる。エラーの内容を見るとDELETEメソッドでリクエストを発行しないといけないのに、GETメソッドでリクエストが発生しているようです。
修正版
method_overrideを有効にして、WebページからのPUTとDELETE の通りに書いていきます。ようするに、formタグをの中に、nameに "_method"
valueに実際送りたいHTTPメソッドを持つhiddenのinputをつけてあげるといいらしい。
hoge.rb
class HogeApp < Sinatra::Base enable :method_override # ここを追加 get "/" do # Hogeの一覧を取得 end delete "destroy_hoge/:number" do # Hogeの削除処理 end end
index.haml
#... %form{action: "/destroy_hoge/#{hoge.number}", method: :post, name: "destory_hoge"} %input{ type: 'hidden', name: '_method', value: 'DELETE' } %input{ type: "submit", value: "Destroy"}
おまけ
こちらの記事 link_to に :method => :delete を指定した時の動作 で
確認しましたが、railsでは link_to
からリクエストを発行する時に、javascriptで書き換えを行なっているっぽいです。railsって便利〜
WebページからのPUTとDELETEの記述で「HTML5より前のHTMLでは、フォームで利用できるHTTPメソッドはGETとPOSTだけである」っていうのは間違えなのかなぁ。