87日目
今日の学習
Ruby on Rails
Couldn't find User with 'id'=***
ゲストログイン機能を実装し、そちらをヘッダーに移して機能の確認をしたところ、ゲストログインができなくなってしまった。
結論としては、実装→ヘッダー導入の間にBootstrapを導入したのだが、そちらのimport部分で誤字があり、JavaScriptが正常に機能しなくなっていたのが原因だった。
なかなか解決に至れず、何時間も浪費してしまったので、解決に至るまでの行程を書き残しておく。
機能実装直後は問題なく動作していたが、突然エラーが出るようになってしまった。
ActiveRecord::RecordNotFound in UsersController#show Couldn't find User with 'id'=guest_sign_in def show @user = User.find(params[:id]) end
なぜかUsersControllerのshow
アクションが呼ばれてしまう。その他のコードを以下に記す。
routes.rb
Rails.application.routes.draw do root 'homes#index' devise_for :users, controllers: { registrations: 'users/registrations', sessions: 'users/sessions', passwords: 'users/passwords' } devise_scope :user do post '/users/guest_sign_in', to: 'users/sessions#guest_sign_in' end resources :users, only: %i[index show] end
app/models/user.rb
def self.guest find_or_create_by(email: 'guest@example.com') do |user| user.name = 'ゲスト' user.biography = 'ゲストユーザーです。' user.password = SecureRandom.urlsafe_base64 end end
app/controllers/users_controller.rb
class UsersController < ApplicationController def index @users = User.all end def show @user = User.find(params[:id]) end end
app/controllers/users/sessions_controller.rb
def guest_sign_in sign_in User.guest redirect_to root_path, notice: 'ゲストユーザーとしてログインしました。' end
app/views/layouts/_header.html.erb
<%= link_to "ゲストログイン", users_guest_sign_in_path, method: :post %>
エラー発生時にはURLの部分が/users/guest_sign_in
となっており、HTTPリクエストでshowアクションが呼ばれて/users/:id
になっているため、そんなIDはないですというエラーが出ている。
そのため、ルーティングに問題があると思い、確認してみたところ、順番は以下のようになっており、問題がない。
users_guest_sign_in POST /users/guest_sign_in(.:format) users/sessions#guest_sign_in users GET /users(.:format) users#index user GET /users/:id(.:format) users#show
エラー発生時のターミナルログは以下のとおり。
Started GET "/users/guest_sign_in" for ::1 at 2021-10-01 13:22:59 +0900 Processing by UsersController#show as HTML Parameters: {"id"=>"guest_sign_in"} User Load (1.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = NULL LIMIT 1 ↳ app/controllers/users_controller.rb:seven:in `show' Completed 404 Not Found in 17ms (ActiveRecord: 5.9ms | Allocations: 2786) ActiveRecord::RecordNotFound (Couldn't find User with 'id'=guest_sign_in): app/controllers/users_controller.rb:seven:in `show'
ここで、冒頭でStarted GET
となっており、POST
となっていないことに気づく。
しっかりとターミナルのログを確認し、意図しているHTTPリクエストになっているかどうかをまずは確認する必要がある。
しかし、検証ではリンクの中身がmethod: :post
となっている。
Ruby on Rails - rails6でPostがGETと認識されてしまう|teratail
似た現象に苛まれている方の解決法を参考に、JavaScriptに問題があるのではないかと推測。
ここで、メンターの方に「デベロッパーツールを開いてJavaScriptのエラーが出ていないか」と助言をいただき、デベロッパーツールで確認。
Consoleを確認してみると、JavaScriptのエラーが発生していた。
それと同時に、なぜかBootstrapのエラーが発生していたので、そちらを確認。
app/javascript/packs/application.js
に、インポートのため以下のコードを記載していた。
import "bootstrap/dist/js/bootstrap"
しかし、bootstrap
ではなくbootstap
と、一文字脱字をしていたためエラーが発生し、JavaScriptが正常に動作しなくなっていた。
Railsでlink_to
を使う際は、JavaScriptを利用してHTTPメソッドを動作させているようで、この脱字が原因でPOSTリクエストが動作しなくなっていたのだった。
Rails学習者にrails-ujsの動作説明したら感動された話 - INODEVLOG
例えば、Viewヘルパーの form_with ( form_for など)の remote: true オプションだったり、 link_to の method: :delete などのオプションを「それっぽく動くように」動作させられるようになります。
誤字を修正すると、問題なくゲストログインが動作するようになり、めでたし。
今回大事だったこと
- ログを確認し、意図した動作になっているのかを確認
なっていなければどうおかしいのかを確認 - デベロッパーツールを活用する
デベロッパーツールに関しては今回初めて活用したこともあり、とにかく色々な機能を使ってエラーの原因を特定することが必要だと感じた。
デベロッパーツールを使わなければBootstrapの誤字にはずっと気づかないままだったと思う。
作業ごとにブランチを分けて開発しており、
- ゲストログイン機能を実装
- Bootstrapを実装
- ヘッダーを実装
という順番で実装していたのだが、1のときは問題なくゲストログイン機能が動作していたため、Bootstrapが何か悪さをしているのではないか...という誤った推測をしてしまい、無駄なことを色々としてしまっていた。
Couldn't find User with 'id'=
に関するエラーを色々調べていたが、link_to
を使ってエラーが起こるのであれば、おそらく大半の原因はJavaScriptが正常に動作していないせいだろう。
学習を始めた直後にlink_to
でdelete
が機能しないと書いていた。
この記事にある、「//= require jquery_ujsと記載することで解決。」とあるが、Rails 5の記述なので解決するはずがないのだが...。
Rails 6からは、JavaScriptはWebpackerで管理する形式になっているため、必ず自分のバージョンを確認してから検索することにしたい。
そして、これまで誤字脱字などのミスは大抵エラーが出てすぐに気づくことができたが、今回は間接的な部分での誤字だったためなかなか発見ができなかった。
普段から誤字を頻発してしまうため、打ち込んだあとは間違えていないか確認する癖をつけようと思った。