プログラミング備忘録

プログラミングの学習状況をメモしています

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が正常に動作しなくなっていた。

Railslink_toを使う際は、JavaScriptを利用してHTTPメソッドを動作させているようで、この脱字が原因でPOSTリクエストが動作しなくなっていたのだった。

Rails学習者にrails-ujsの動作説明したら感動された話 - INODEVLOG

例えば、Viewヘルパーの form_with ( form_for など)の remote: true オプションだったり、 link_to の method: :delete などのオプションを「それっぽく動くように」動作させられるようになります。

誤字を修正すると、問題なくゲストログインが動作するようになり、めでたし。

今回大事だったこと

  • ログを確認し、意図した動作になっているのかを確認
    なっていなければどうおかしいのかを確認
  • デベロッパーツールを活用する

デベロッパーツールに関しては今回初めて活用したこともあり、とにかく色々な機能を使ってエラーの原因を特定することが必要だと感じた。

デベロッパーツールを使わなければBootstrapの誤字にはずっと気づかないままだったと思う。

作業ごとにブランチを分けて開発しており、

  1. ゲストログイン機能を実装
  2. Bootstrapを実装
  3. ヘッダーを実装

という順番で実装していたのだが、1のときは問題なくゲストログイン機能が動作していたため、Bootstrapが何か悪さをしているのではないか...という誤った推測をしてしまい、無駄なことを色々としてしまっていた。

Couldn't find User with 'id'=に関するエラーを色々調べていたが、link_toを使ってエラーが起こるのであれば、おそらく大半の原因はJavaScriptが正常に動作していないせいだろう。

学習を始めた直後にlink_todeleteが機能しないと書いていた。

11日目 - プログラミング備忘録

この記事にある、「//= require jquery_ujsと記載することで解決。」とあるが、Rails 5の記述なので解決するはずがないのだが...。

Rails 6からは、JavaScriptはWebpackerで管理する形式になっているため、必ず自分のバージョンを確認してから検索することにしたい。

そして、これまで誤字脱字などのミスは大抵エラーが出てすぐに気づくことができたが、今回は間接的な部分での誤字だったためなかなか発見ができなかった。

普段から誤字を頻発してしまうため、打ち込んだあとは間違えていないか確認する癖をつけようと思った。