1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

namespace付きのControllerでredirect_toをする時は要注意

Posted at
Rails: 5.2.4.4

概要

例えば以下のようなルーティングがあります。

routes.rb
resources :top
resources :users
namespace :admin do
  resources :companies
end

以下はrails routesの実行結果(から抜粋)

top_index       GET    /top(.:format)                 top#index
users           GET    /users(.:format)               users#index
admin_companies GET    /admin/companies(.:format)     admin/companies#index

各コントローラーはApplicationControllerを継承している

application_controller.rb
class ApplicationController < ActionController::Base
  before_action :login_required
  
  def login_required
    redirect_to controller: :top, action: :index unless current_user
  end
end

ログインしていない時は top#indexにリダイレクトする、という実装ですね。

さて、ログインしていない状態で/usersにアクセスを試みると/topにリダイレクトします。
同様に/admin/companiesにアクセスを試みると/topに0ダイレクトする・・・かと思いきや、500エラーが起きます。なぜ?
 

原因

発生したエラーを見ると以下のようになっていました。

No route matches {:action=>"index", :controller=>"admin/top"}

つまり、adminのnamespace内でtop#indexにリダイレクトしようとしており、そんなルーティングは存在しないのでエラーになっていた、と。。

対策

名前付きルーティングヘルパーを使うと良さそうです。

application_controller.rb
  def login_required
-    redirect_to controller: :top, action: :index unless current_user
+    redirect_to top_index_url unless current_user
  end

まとめ

RSpecを書いていた時に今回のエラーに遭遇し、3時間ほどハマりました...
共通処理かつ他のコントローラーテストでは通っていた(⇔ namespaceのあるコントローラーでリダイレクトするケースがなかった)ので、ここの箇所ではないはず、と先入観を持ってしまったんですよね。。

わかってしまえば単純なことなので、記憶の片隅にとどめておきましょう。
リダイレクトを実装する時は、名前付きルーティングヘルパーを使っておくのが無難そうです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?