Rails初学者がやりがちな5つのミス、まとめてみました
Rails初学者がやりがちな5つのミス、まとめてみました
それがこちら。
- nilオブジェクトへの呼び出し、メソッドのタイポや未定義
- DBに存在しないレコードを参照している
- パラメータ構造とコントローラ設定がずれている(ストロングパラメータ関連)
- テーブルやカラムがまだDBに作られていない(マイグレーションの実行漏れ)
- routes.rbに必要なルートが未定義(ルーティング設定の抜け)
これらを、下記の3つの観点から解説します。
- 事象(ミスっている内容)
- 遭遇するエラーメッセージ
- 主な原因と対処法
ではでは、早速解説へ。
1. nilオブジェクトへの呼び出し、メソッドのタイポや未定義
遭遇するエラーメッセージ
NoMethodError: undefined method `full_name' for nil:NilClass
NoMethodError: undefined method `ful_name' for #<User:0x00007f9c8e2c9a20>
主な原因と対処法
-
原因1: 変数自体がnilで、呼び出し対象のインスタンスが存在しない(このパターン、めっちゃ多い)
-
対処法:
- Rails consoleで該当のインスタンスを取得できるか確認してください
- コントローラやモデル内で
@user.present?
など、nilチェックを入れて想定どおりの値が入っているか調べてください
-
対処法:
-
原因2: メソッド名のつづりが誤っている('full_name'のつもりが'ful_name' など)
-
対処法:
- コントローラやモデルで定義しているメソッド名を再確認してください(エディターで文字列検索してヒットするか確認する、など)
- Rails consoleで
User.instance_methods
などを呼び出し、そのメソッドが本当に存在するか確かめてください
-
対処法:
-
原因3: モデルにメソッドを定義していない、またはprivateメソッドで呼び出せない
-
対処法:
- モデルのファイルを見て、メソッドが定義されているか確認してください
- 意図せずprivate配下に記述していたとしたら、publicメソッドとして定義してください
- 例:
class User < ApplicationRecord def full_name "#{first_name} #{last_name}" end private # プライベートメソッドに記述されている場合は上部に移動 end
-
対処法:
2. DBに存在しないレコードを参照している
遭遇するエラーメッセージ
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=999
主な原因と対処法
-
原因1: 指定したID(params[:id]など)がDBに存在しない
-
対処法:
- Rails consoleで下記を実行し、本当にレコードがあるかチェックしてください
$ rails console > User.find(999)
- Rails consoleで下記を実行し、本当にレコードがあるかチェックしてください
-
対処法:
-
原因2: where句などの条件によってヒットしない
-
対処法:
- Userモデルのスコープを使用していた場合、その条件が意図通りか確認してください
- 例:
class User < ApplicationRecord scope :active, -> { where(active: true) } end User.active.find(999)といったコードを書いていたら、上記のエラーになる可能性がある。
-
対処法:
3. パラメータ構造とコントローラ設定がずれている(ストロングパラメータ関連)
遭遇するエラーメッセージ
Unpermitted parameters: :name
もしくはログにのみ警告が出て、保存されないケース
Started POST "/users" for 127.0.0.1
Unpermitted parameters: :name
主な原因と対処法
-
原因1: form_withやform_forから送信されるパラメータとストロングパラメータの記述が噛み合っていない
-
対処法:
- コントローラ側のpermitに必要なキーを追加してください
private def user_params params.require(:user).permit(:name, :email) end
- コントローラ側のpermitに必要なキーを追加してください
-
対処法:
-
原因2: ネストされたフォームを使用していて、キー階層が合っていない
-
対処法:
- ビューのHTMLソースをチェックし、'user[name]'がどう送られるかを確認してください
- コントローラで
p params
して、実際どのキーが送られているかを確かめてください
-
対処法:
4. テーブルやカラムがまだDBに作られていない(マイグレーションの実行漏れ)
遭遇するエラーメッセージ
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'my_app_development.users' doesn't exist
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'users.email' in 'field list'
主な原因と対処法
-
原因1: モデルやマイグレーションを作成後、
rails db:migrate
を実行し忘れている-
対処法:
- 必ず以下を実行してください
$ rails db:migrate
- 必ず以下を実行してください
-
対処法:
-
原因2: マイグレーションが途中で失敗してテーブルやカラムが作られていない
-
対処法:
- ターミナルでエラーログを確認し、原因を修正したら再度
rails db:migrate
を試してください -
rails db:migrate:status
を使うと、未実行のマイグレーションファイルが残っていないか確認できます
- ターミナルでエラーログを確認し、原因を修正したら再度
-
対処法:
5. routes.rbに必要なルートが未定義(ルーティング設定の抜け)
遭遇するエラーメッセージ
ActionController::RoutingError (No route matches [GET] "/articles")
主な原因と対処法
-
原因1: config/routes.rbに必要なルートを宣言していない
-
対処法:
-
rails routes
を実行し、目的のパスが定義されているか確かめてください - 必要ならroutes.rbに
resources :articles
などを追加してください
-
-
対処法:
-
原因2: 同じパスを複数定義してしまい、意図しないルートにマッチしている
-
対処法:
- routes.rbを見直し、重複ルートを削除してください
- 似たようなパスがある場合、別のパス名やスコープを使うなど明確に区別してください
-
対処法:
-
原因3:
resources :xxx
などの自動生成ルートを誤解している-
対処法:
-
rails routes
で生成されたパスを確認し、正しいURL・HTTPメソッドを把握してください - 不要なルートが含まれている場合は
only:
やexcept:
オプションを使って制限しましょう
-
-
対処法:
まとめ
「初学者がやりがち」と書きましたが、この5つの事象はエンジニアだったらいつでも出くわすエラーだと思います。
初代のズバットみたいな感じで、序盤のオツキミ山に出てくるポケモンと思いきや、チャンピオンロードにも出現してきて不意を突かれます。
「このパターンはこれが原因かもなー」という知識を頭の片隅に置いておくと、Rails学習時のトラブルシュートがぐっとスムーズになるはずです。ぜひ参考にしてみてください。
Discussion