config/routes.rb の末尾に *path などのルーティングがあると、
ActiveStorageのファイルを示すエンドポイント(/rails/active_storage/...)1よりも先にマッチしてしまう。
Rails.application.routes.draw do
...
get "*path" , to: redirect('/')
end
これを回避するためには以下のようにする。
Rails.application.routes.draw do
...
get '*path' , to: redirect('/'), constraints: lambda { |req|
req.path.exclude? 'rails/active_storage'
}
end
これで rails/active_storage を含むパスがマッチしないように設定できる。
constraints オプションについて
特定のルーティングに制約(constraints)を与えるためのオプションという解釈。
以下のようにして使う。
# match `/users/A12345`, but not `/users/893`
get 'users/:id', to: 'users#show', constraints: { id: /[A-Z]\d{5}/ }
# match port 3000 only
get :users, to: 'users#index', constraints: { port: '3000' }
上述のようにlambdaを指定することもできる。2
get "hi", to: redirect("/foo"), constraints: ->(req) { true }
参考
- https://qiita.com/NaokiIshimura/items/0f0e56c159c95b59b11f
- https://github.com/rails/rails/issues/31228#issuecomment-352900551
- https://y-yagi.tumblr.com/post/92386974040/rails-routing-constraintsについて
- https://railsguides.jp/routing.html#セグメントを制限する
-
定義はこちら https://github.com/rails/rails/blob/v5.2.4.4/activestorage/config/routes.rb#L4 ↩
-
厳密には
requestを引数に取るcallメソッドが呼び出し可能なオブジェクトを指定すればよさそう。リクエスト毎に呼ばれるcallがtrueを返す場合にのみ、対象のルーティングがマッチするといった動作のよう。本投稿では触れていないがmatches?でも可。 ( テストコード 、 実装部分 を参照) ↩