SinatraでHTTPメソッドのDELETEを実現する

SinatraでHTTPメソッドのDELETEを実装する時かなりはまったのでメモです。実はもっと賢いやり方があるのかもしれないので、コメント大歓迎(基本的に僕のブログは全部そうです)。

今回は間違ったところから書きました。

使用環境

です。

関係しそうなもの

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だけである」っていうのは間違えなのかなぁ。