💬

[Rails]管理者コメント管理機能(ルーティング)(collection)

2025/02/07に公開

今回起きたエラー

ルーティングでこの書き方だと

 namespace :admin do
    resources :users, only: [:destroy]
    resources :dashboards, only: [:index, :search]
    resources :comments, only: [:index, :destroy]
    resources :tasks, only: [:index, :destroy]
  end

このエラーが出る。

admin_dashboards_search_path というルートが存在しないために発生している。

namespace :admin do
  resources :dashboards, only: [:index, :search]
end

この部分でindex と search の 2つのアクション を定義しようとしているが
resources の only: には ルートのHTTPメソッド(index, show, new, create, edit, update, destroy など) しか指定できない。
しかし、 search はデフォルトのルートには含まれていないため、正しくルーティングが設定されない。

resources :dashboardsindexsearch2つのアクション を定義しようとしているが、 resourcesルートのHTTPメソッド(index, show, new, create, edit, update, destroy など) しか指定できない。

resourcesを宣言するだけで、コントローラのindex、show、new、edit、create、update、destroyアクションを個別に宣言しなくても1行で宣言が完了します。

引用元:Railsガイド

search はデフォルトのルートには含まれていないため、正しくルーティングが設定できない。


解決策

collection を追加する

search は、特定の id に依存しない検索アクションなので、 collection を使って定義する。

collectionという用語は、複数の要素(要素のコレクション)を操作するルーティング(indexルーティングなど)を指します。
上のルーティングは、GETリクエスト + /photos/searchなどの(idを伴わない)パスを認識し、リクエストをPhotosコントローラのsearchアクションにルーティングします。このときsearch_photos_urlやsearch_photos_pathルーティングヘルパーも同時に作成されます。

引用元:Railsガイド

修正後の config/routes.rb

namespace :admin do
  resources :users, only: [:destroy]
  resources :dashboards, only: [:index] do
    collection do
      get :search
    end
  end
  resources :comments, only: [:index, :destroy]
  resources :tasks, only: [:index, :destroy]
end

解説

  • collection do ... end を使うことで、 search アクションの ルートを明示的に追加
  • これにより、以下のようなルートが生成される。
$ rails routes | grep admin

admin_dashboards_index GET  /admin/dashboards(.:format)        admin/dashboards#index
admin_dashboards_search GET  /admin/dashboards/search(.:format) admin/dashboards#search

エラーその2

chatGPTは「上記修正をした後、form_withurl: はそのままOK。」と言っていたが、エラーが出た!なので、これは嘘!!

<%= form_with url: admin_dashboards_search_path, method: :get, local: true do |f| %>

パスヘルパー命名規則

毎回パスヘルパーの書き方で悩むので、まとめます!
Rails のルーティングのヘルパー名は、以下の 3つの要素の組み合わせ で決まる!

[アクション名] + [リソース名(複数形)] + path

🚀 ルートの種類ごとの命名規則

ルートの種類 記述方法 URLパターン 生成されるヘルパー名
通常のリソース resources :tasks /tasks tasks_path
特定の ID を持つ単数リソース resources :tasks /tasks/:id task_path(@task)
collection で定義(IDなし) collection do get :search end /tasks/search search_tasks_path
member で定義(IDあり) member do get :search end /tasks/:id/search search_task_path(@task)
名前空間(namespace)あり namespace :admin do resources :tasks end /admin/tasks admin_tasks_path
名前空間 + collection namespace :admin do resources :tasks do collection { get :search } end /admin/tasks/search search_admin_tasks_path
名前空間 + member namespace :admin do resources :tasks do member { get :search } end /admin/tasks/:id/search search_admin_task_path(@task)

admin_dashboards_search_path にならなかった

routes.rb では次のように collectionsearch を定義 したから。

namespace :admin do
  resources :dashboards, only: [:index] do
    collection do
      get :search
    end
  end
end

この場合の命名規則:

[アクション名] + [名前空間付きのリソース名] + path
= search + admin_dashboards + path
= search_admin_dashboards_path

admin_dashboards_search_path ではなく search_admin_dashboards_path になったのは、この命名ルールに従っているため!


admin_dashboards_search_path にするには?

config/routes.rbas: "admin_dashboards_search" を追加することで変更できます。

namespace :admin do
  resources :dashboards, only: [:index] do
    collection do
      get :search, as: "admin_dashboards_search"
    end
  end
end

これを適用すると、命名規則が変わり:

[カスタム名] + path
= admin_dashboards_search + path
= admin_dashboards_search_path

参考文献

https://railsguides.jp/routing.html#リソースベースのルーティング-railsのデフォルト

https://railsguides.jp/routing.html#コレクションルーティングを追加する

Discussion