めもめも のーと

ハマったこととか、覚えたこととか

RailsでページによってSingOutのURLが変わってしまった件

Ruby on Rails はviewの共通テンプレートがあり、そこにsign in / out のリンクをつけることが多いと思います。

ただしroutingの設定によっては思わぬURLが生成されることもあるので注意が必要です。


【環境】
ruby1.8.7
rails 2.3.8

次のようなリンクを${RAILS_ROOT}/app/view/layout の共通テンプレートファイルに書いていました。

<%= link_to t('consumer.header.signout'), { :controller => :sessions, :action => :destroy }, :confirm => t('consumer.header.signout_confirmation'), :method => :delete %>

商品詳細ページ以外で生成されるURLは次のようなもの。

/consumer/sessions/destroy

商品詳細ページでヘッダー部分のsign outをクリックすると、↓のようなエラーが起きました!

Processing Consumer::SessionsController#1137 (for XXX.XXX.XXX.XX at 2013-05-13 11:19:52) [GET]
2013/05/13 11:19:52 [INFO]   Parameters: {"action"=>"1137", "controller"=>"consumer/sessions"}

・・・

2013/05/13 11:19:52 [ERROR] ActionController::UnknownAction
2013/05/13 11:19:52 [ERROR] No action responded to 1137. 

おかしいなーと思って、rake routesしてみると、、

$ rake routes | grep session
   consumer_sessions POST   /consumer/sessions(.:format)        {:controller=>"consumer/sessions", :action=>"create"}  
new_consumer_session GET    /consumer/sessions/new(.:format)    {:controller=>"consumer/sessions", :action=>"new"}
consumer_session     DELETE /consumer/sessions/:id(.:format)    {:controller=>"consumer/sessions", :action=>"destroy"}

商品詳細ページで生成されるURLはこんな↓になっていました。

/consumer/sessions/1137

DELETE の /sessions/:id のところの「:id」が、商品詳細ページに遷移するときのパラメータのid( "id"=>"1137")を拾ってあんなURLを作ってしまっていたんですね。。

  • 商品詳細ページへ遷移するときのログ。
Processing Consumer::ItemsController#show (for XXX.XXX.XXX.XX at 2013-05-13 19:46:06) [GET]
  Parameters: {"action"=>"show", "id"=>"1137", "controller"=>"consumer/items"}

対処法

route.rbを次のように修正して、ルーティング設定を見直しました。

map.namespace(:consumer) do |consumer|
・・・
    consumer.signout '/sessions/destroy', :controller => :sessions, :action => :destroy    <= 追加
    #consumer.resources :sessions, :except => [:index, :edit, :show, :update]              <= 元々
    consumer.resources :sessions, :except => [:index, :edit, :show, :update, :destroy]     <= 修正

rake routesしてみると↓のようになり、 無事全ページでsign outのURLが /consumer/sessions/destroy になりました。

$ rake routes | grep session
    consumer_signout        /consumer/sessions/destroy          {:controller=>"consumer/sessions", :action=>"destroy"}
   consumer_sessions POST   /consumer/sessions(.:format)        {:controller=>"consumer/sessions", :action=>"create"}
new_consumer_session GET    /consumer/sessions/new(.:format)    {:controller=>"consumer/sessions", :action=>"new"}

まとめ

idを伴わないdestroyをする場合は、routingが正しく設定されているか、要確認!