😇

【Rails】deviseアクセス制限時の注意点

2023/11/24に公開

前回、下記の記事にてdeviseにて他者からのアクセス制限に関する復習をしましたが、その中で記述の違いで発生したエラーがありましたのでここに記録しておきます。
https://zenn.dev/sudoukky/articles/5436a349141890

前回の記述方法

前回のアクセス制限をかける際の記述方法ではルーティングがresourcesを使って作成されたものに適応される内容で、主に編集画面内でのform_withの記述に違いがあります。resourcesを使用する場合は、下記のように記述します。

views/users/edit.html.erb
<%= form_with model: @user do |f| %>
<div class="row mt-3">
  <h5 class="col-3">名前</h5>
  <%= f.text_field :name ,class:"col-3" %>
</div>
<div class="row mt-3">
  <h5 class="col-3">メールアドレス</h5>
  <%= f.text_field :email ,class:"col-3"%>
</div>
  
  <%= f.submit '変更を保存',class: 'btn btn-success mt-3' %>
  
<% end %>

今回起きた問題

resourcesを使わず下記のようにルーティングを設定していました。

routes.rb
scope module: :public do
    
    get 'top' => 'homes#top', as: 'top'
    get 'about' => 'homes#about', as: 'about'
    
    get 'users/my_page' => 'users#show', as: 'user' 
    get 'users/information_edit' => 'users#edit', as: 'users_information_edit'
    patch 'users/information' => 'users#update', as: 'users_information'
    get 'users/favorites' => 'users#favorites', as: 'user_favorites'
    :

上記のルーティングで先ほどのform_withとコントローラにbefore_action :is_matching_login_user, only: [:edit, :update]を記述した場合に、エラーが発生しました。
ActiveRecord::RecordNotFound in Public::UsersController#update Couldn't find User with 'id'=my_page
というエラーが発生し、原因としては、マイページにアクセスしてプロフィールを更新しようとした際に、指定されたidのユーザーが存在しないため、エラーが発生してしまっています。
直接の原因は上記のルーティング内でget 'users/my_page' => 'users#show', as: 'user' の記述の後にeditやupdateの記述があるため、上から順に読み込まれた際にidが存在していないと判断されています。

エラーを防ぐためには、ルーティングの順番を入れ替えるかform_withに細かいidの情報を与える必要があります。今回は後者の場合の記述をやっていきます。

views/users/edit.html.erb
<%= form_with model: @user,url: users_information_path(id: current_user.id) do |f| %>
<div class="row mt-3">
  <h5 class="col-3">名前</h5>
  <%= f.text_field :name ,class:"col-3" %>
</div>
<div class="row mt-3">
  <h5 class="col-3">メールアドレス</h5>
  <%= f.text_field :email ,class:"col-3"%>
</div>
  
  <%= f.submit '変更を保存',class: 'btn btn-success mt-3' %>
  
<% end %>

<%= form_with model: @user,url: users_information_path(id: current_user.id) do |f| %>の部分では、先ほどと違い@userオブジェクトに対して送信先のURLを記述し、idパラメータに現在のユーザーのidを設定したURLを表すことで先ほどのエラーが解消されます。

まとめ

普段、ルーティング作成時にresourcesを使用することが多く、ルーティングの順番を意識することが薄れていたのが今回のエラーの原因だったと思います。今後はルーティングの順番とルーティングが及ぼす影響等を考えて作成できるようにしていきます。

Discussion