ヨージとプログラミング

プログラミング勉強の記録

【Rails】routesの設定で「resource」と「resource"s"」の違いで小一時間悩んだ話

DELETEのrouteに:idと:user_idの2つ現れてしまった

routesをネストした時に、resourcesと単数形でなかればならないところを複数形で書いてエラーになりました。なんのこっちゃだと思うのでまずはコードを見てください。

# 誤ったコード
Rails.application.routes.draw do
  #          (中略)
  resources :users do
    resources :relationships, only: [:create, :destroy]
  end
  resources :records
end

resources :usersrelationshipsがネストされていると思います。
目的としては、/users/:user_id/relationshipsのようなパスにしたかったためです。これだと、relationshipsリソースでuser_idが利用しやすくなるからです。
ただ、実際にroutesを確認してみると目論見とは異なるルートとなっていました。

$ docker-compose run web rails routes
=>
            Prefix Verb   URI Pattern                                      Controller#Action
             about GET    /about(.:format)                                 static_pages#about
             login GET    /login(.:format)                                 sessions#new
                   POST   /login(.:format)                                 sessions#create
            logout DELETE /logout(.:format)                                sessions#destroy
              root GET    /                                                users#index
user_relationships POST   /users/:user_id/relationships(.:format)          relationships#create
 user_relationship DELETE /users/:user_id/relationships/:id(.:format)      relationships#destroy

#                         (以下略)

上記のここです

user_relationships POST   /users/:user_id/relationships(.:format)          relationships#create
user_relationship DELETE /users/:user_id/relationships/:id(.:format)      relationships#destroy

POSTの方は問題ないのですが、DELETEの方は:user_id:idの2つの要素が入ってきてしまって今回は困ってしまいました。これは典型的なfollow/follower機能の実装で、followerのdeleteでは:user_idの方しか使わないからです。かといって、:idの方を放置していいのかというと、それはルートエラーになります。

複数無いものは「resouce」を使う

結論を申し上げますと、ネストの中の:relationshipsのresourcesを単数のresourceにすると上手く行きました。

# 修正したコード
Rails.application.routes.draw do
  #          (中略)
  resources :users do
    resource :relationships, only: [:create, :destroy]
  end
  resources :records
end

種がわかれば当たり前のことですが、複数形resourcesということは複数あると宣言しているわけですから、:idや:user_idなどで枝番が付くわけです。
当たり前だろ!っとお思われる方も多いと思いますが、少しググったところで明確に注意喚起しているページもありませんでしたので書いてみました。

$ docker-compose run web rails routes
=>
            Prefix Verb   URI Pattern                                      Controller#Action
             about GET    /about(.:format)                                 static_pages#about
             login GET    /login(.:format)                                 sessions#new
                   POST   /login(.:format)                                 sessions#create
            logout DELETE /logout(.:format)                                sessions#destroy
              root GET    /                                                users#index
user_relationships DELETE /users/:user_id/relationships(.:format)          relationships#destroy
                   POST   /users/:user_id/relationships(.:format)          relationships#create

#                         (以下略)