実現したいこと
・deviseでユーザー認証機能を導入したい
・その過程で、自分以外のユーザーのプロフィールを編集できないようにしたい
・ユーザーのプロフィールページに置かれたリンクをクリックすることで、プロフィールの編集ページに移動させたい
発生している問題・エラーメッセージ
上記の機能をprotectedメソッドとして定義してみたのですが、プロフィールの編集のリンクを押したところ、編集ページ(registrations#edit)に入れませんでした。
ブラウザには下記のエラーが表示されています。
ActiveRecord::RecordNotFound in Users::RegistrationsController#edit Couldn't find User without an ID # edit, updateアクションを現在のユーザーのみに限定する def correct_user @user = User.find(params[:id]) redirect_to(root_url) unless @user == current_user end
該当のソースコード
Railstutorialを参考にprotectedメソッドにcorrect_userを定義しました。
ただ、これが原因でエラーが出ているようです。
Ruby
1# frozen_string_literal: true 2 3class Users::RegistrationsController < Devise::RegistrationsController 4 before_action :authenticate_user!, only: [:edit, :update, :destroy] 5 before_action :correct_user, only: [:edit, :update] 6 7 def new 8 super 9 end 10 11 def create 12 super 13 end 14 15 def edit 16 super 17 end 18 19 def update 20 super 21 end 22 23 def destroy 24 super 25 end 26 27 protected 28 29 # edit, updateアクションを現在のユーザーのみに限定する 30 def correct_user 31 @user = User.find(params[:id]) 32 redirect_to root_path unless @user == current_user 33 end 34 35end 36 37
該当のview
こちらはdeviseと関係なく作成したユーザーのプロフィールページ(users#show)です。
「プロフィールの編集」リンクを押して、プロフィール編集画面に移動する際に上記のエラーがでました。
このページは正しく表示されています。
Ruby
1<% provide(:title, @user.name) %> 2 3<h3>プロフィール</h3> 4<p>名前 : <%= @user.name %></p> 5<p>メールアドレス: <%= @user.email %></p> 6 7<%= link_to 'プロフィールの編集', edit_user_registration_path(@user) %>
routes.rb
Ruby
1Rails.application.routes.draw do 2 root 'static_pages#home' 3 get '/help', to:'static_pages#help' 4 get '/about', to:'static_pages#about' 5 get '/contact', to:'static_pages#contact' 6 devise_for :users, :controllers => { 7 :confirmations => 'users/confirmations', 8 :registrations => 'users/registrations', 9 :sessions => 'users/sessions' 10 } 11 devise_scope :user do 12 get "sign_in", to:"users/sessions#new" 13 delete "sign_out", to:"users/sessions#destroy" 14 end 15 resources :users, only: [:index, :show] 16end 17
試したこと
Rspecでregistrations_controllerのテストをしました。
そのテストはパスするのですが、そもそも正しいテストを書けているか自信がありません。
念のため、以下にテスト内容とテストデータ(FactoryBot)を記載します。
Ruby
1require 'rails_helper' 2 3describe Users::RegistrationsController, type: :controller do 4 let(:user) { create(:user) } 5 let(:other_user) { create(:other_user) } 6 7 # ユーザー情報編集ページの表示をテスト 8 describe 'GET #edit' do 9 # ログインしている場合 10 context 'with logged in' do 11 # edit(ユーザー情報編集)ページの検証 12 it 'responds successfully' do 13 @request.env["devise.mapping"] = Devise.mappings[:user] 14 sign_in user 15 get :edit, params: { id: user.id } 16 expect(response).to have_http_status "200" 17 expect(response).to render_template :edit 18 end 19 end 20 # ログインしていない場合 21 context 'without logged in' do 22 # edit(ユーザー情報編集)ページの代わりにsign_in(ログイン)ページを返すか検証 23 it 'redirect to new_session_path' do 24 @request.env["devise.mapping"] = Devise.mappings[:user] 25 get :edit, params: { id: user.id } 26 expect(response).to have_http_status "302" 27 expect(response).to redirect_to new_user_session_path 28 end 29 end 30 # 他のユーザーでログインしている場合 31 context 'with logged in as other user' do 32 # ルートにリダイレクトされるか検証 33 it 'redirect to root_path' do 34 @request.env["devise.mapping"] = Devise.mappings[:user] 35 sign_in other_user 36 get :edit, params: { id: user.id } 37 expect(response).to have_http_status "302" 38 expect(response).to redirect_to root_path 39 end 40 end 41 end 42 43end
Ruby
1FactoryBot.define do 2 3 factory :user, class: User do 4 name { 'foo' } 5 email { 'foo@test.com' } 6 password { 'foo123' } 7 password_confirmation { 'foo123' } 8 confirmed_at { Date.today } 9 end 10 11 factory :other_user, class: User do 12 name { 'bar' } 13 email { 'bar@test.com' } 14 password { 'bar123' } 15 password_confirmation { 'bar123' } 16 confirmed_at { Date.today } 17 end 18 19end
確認したこと
correct_userがなければ編集ページに移動できることは確認しており、その際URLにはユーザーのIDが記載されていました。そのため、IDが見つからないからユーザーを検索できないというエラーの原因がわかりませんでした。
1日悩んでわからなかったので、どなたか原因を教えていただけないでしょうか。
質問に不備がある場合は遠慮なく伝えていただけると幸いです。
どうぞよろしくお願いします。
補足情報(FW/ツールのバージョンなど)
ruby 2.7.1
Rails 6.0.3.2
回答1件
あなたの回答
tips
プレビュー