railsでdeviseを用いてログイン系機能を実装しているときにちょっと悩んでしまったのでメモ。
状況
railsでdeviseをインストールし、ログインはできるようになっている。
ログアウトのリンクを作成したが、リンクをクリックすると、
NameError - uninitialized constatnt Usersontroller:
が発生してログアウトができない。
ちなみに作成したログアウトのリンクは、
<%= link_to 'Log Out', destroy_user_session_path %>
環境
手順概要
ログアウトがセッションの破棄ということを踏まえて、データの削除時に行っていたようにmethodオプションでdeleteということを示しましょう。
手順詳細
ログアウトのリンクを以下のように書きましょう。
<%= link_to 'Log Out', destroy_user_session_path, method: :delete %>
そのほか
NameErrorと出ていたので、自分がよくやるタイプミスが原因かなと思ってソースをちまちまチェックしていていましたが、珍しくタイプミスではなかったようでした・・・(汗)
methodを指定しないとGETリクエストが送られてしまい、deleteメソッドでのdestroy_user_session
はないよということでしょうか。でもそれならrouting errorになってもよさそうですが…。
そもそもなぜDELETEの時はmethodオプションを付けないといけないのか、軽く調べてみました
- method: :deleteを指定するとどうなるのか?
こちらのサイトを参考にしました。ありがとうございます。
link_to に :method => :delete を指定した時の動作 - happy lie, happy life
まず、Railsのlink_toにおいてmethod: :delete
を指定すると、HTML上のaタグ内でdata-method="delete"
を指定するということになるそうです。
そして、rails.jsがaタグをうまいこと解釈してくれて、最終的にはformタグから_methodを指定した状態で実行されるので削除できる、ということみたいです。 - どうしてこのような流れを踏むのか?
ちょうどお家にあった『Webを支える技術 HTTP,URI,HTML,そしてREST』(技術評論社・2010年)を参考にしました。
まず、「7.9 POSTでPUT/DELETEを代用する方法」の項目で 「HTMLのフォームで指定できるメソッドがGETとPOSTだけという制限に起因します。」とあるように、HTMLのFormはGETとPOST以外のリクエストをデフォルトでは受け入れていないようです。
ですが、_methodパラメータを用いることでその制約から逃れることができるようです。
そういった経緯があってRailでのDELETE実行のためにはmethod: :delete
を指定する必要があるようです。
railsに全頼りでrails視点でしか考えていませんでしたが、htmlをはじめとした基盤の上に成り立っているのだなあと再認識する良いきっかけとなりました。