トラブルシューティング
Ruby on Railsのカリキュラムを進めていく上でよく発生するエラーについて。
作成中のrailsアプリケーションを操作するにはrails sコマンドで開発用サーバーを立ち上げアプリケーションに接続する。
この時、コードが間違ったり正常ではない状態で操作を行おうとするとエラーが発生する。
エラー画面を読んでみる
エラー画面を読めるようになれば、エラーの原因がどこにあるのかを推察することができる。
原因がわかれば、それを正すことも簡単である。エラー画面を読めるようになれば、開発効率がぐんと上がる。
【例】(一例として「NoMethodError」の画面を使用)
①エラーのタイトル
エラーの内容を端的に表す。上の例は、「NoMethodError」というタイトルのエラー。「Tweets#index」は、tweetsコントローラーのindexアクションでエラーが起きた、という意味。
②エラーが起きたコードの場所
実際にどのファイルのコードがエラーを起こしているかを示す。上の例は、「・・・views/tweets/index.html.erb」の「line #3」、つまり3行目でエラーが起こっているということになる。
③エラーの具体的な内容
エラーの具体的な内容を示す。上の例は、「eac」というメソッドは<#Tweet::Activerecord_relation・・・>というインスタンスには使えないということになる。
④エラーが起きたコードの表示
エラーが起きた箇所の前後が表示される。ピンクのラインの部分がエラー箇所。
エラーの種類について
エラーには、Rubyの文法エラーとRuby on Railsのエラーの2種類がある。
Rubyの文法エラーとは、例えばif文などのendを書き忘れなどで起こるもの。
Railsのエラーとは、Railsの仕組み、決まりに違反している場合に起こるエラー。例えば、実行されていないマイグレーションファイルがある場合や、ルーティングの設定のし忘れ、viewファイルが無い場合などに起こる。
Railsで良く出現するエラー文を以下のようにタイトルのアルファベット順に挙げる。
NoMethodError
Pending migration error
Routing Error
syntax error
Template is missing
エラーが起きたらまずは以下を参照して、解決を目指す。
よくあるエラー一覧
NoMethodError in [問題箇所のコントローラー]#アクション
エラーの種類
Rubyの文法エラー
NoMethodError
メソッドを使用されたインスタンスのクラスにそのメソッドが定義されていなかったり、リクエストで指定されたコントローラーにそのアクションが無い場合に起こるエラー。
undefined method `[メソッド名]' for [メソッドを使用されたインスタンス]
【例】
【解決法】 以下の箇所をチェック。
①そのインスタンスのクラスに定義されているメソッドを使用しているか?
以下の例のように、メソッドを使用するインスタンスのクラスに定義されていないメソッドを使用するとエラーになる。
【例】
1 2 3 |
100.each do |num| #数字クラスのインスタンスにeachメソッドは定義されていないのでエラーになる
puts num
end
|
メソッドを使用する際は、使用されるインスタンスがどのクラスのインスタンスなのかを意識する。
②メソッドを使用しているインスタンスがnilになっていないか?
エラーメッセージの後半が「`[メソッド名]' for nil::nilclass」となっている場合、メソッドを使用しているインスタンスがnilになっている。そのインスタンスを生成している箇所を調べてみる。
よくあるのは以下の例のような、部分テンプレートでの「'nickname' for nil::nilclass」エラー。
【例】
1つのtweetは1人のuserに属している、という関係の時、tweetsテーブルのuser_idカラムが空だと、tweetがどのuserのものか判断できない。すると、tweet.userはnilになる。そのため、上記のようなエラーになる。
Pending migration error
エラーの種類
Railsのエラー
Pending migration error
実行していないマイグレーションファイルがあると起こるエラー。
Migrations are pending. To resolve this issue, run: bin/rake db:migrate RAILS_ENV=development
【例】
【解決法】 以下の箇所をチェック。
①実行していないマイグレーションファイルがないか?
マイグレーションファイルを作成したが、実行するのを忘れている場合がある。
rake db:migrateコマンドでマイグレーションファイルを実行。
Routing Error
エラーの種類
Railsのエラー
Routing Error
リクエストしたルーティングが設定されていないと起きるエラー。
ルーティングの確認はもちろん、間違ったルーティングをリクエストしていないか確かめる必要がある。
No route matches [#HTTPメソッド] "#リクエストしたルーティング"
【例】
【解決法】 以下の箇所をチェック。
①routes.rbで設定しているルーティングの記述は合っているか?
routes.rbを開き、リクエストしたいルーティングの記述が正しいかどうかを確かめる。
半角スペースや''(クォーテーション)、/(スラッシュ)などが抜けていないか?
②リクエストしている箇所のパスの記述は合っているか?
エラー文が出ている画面のurl(下図参照)を見ると、実際に送られたパスを確認することができる。
これがroutes.rbで設定したルーティングと違う場合、パスをリクエストした箇所の書き方が間違っている可能性がある。リクエスト元のviewファイルを開き、正しく書けているか確かめる。
よくある間違いは、以下の例のように、'tweets/:id'という風にroutes.rbの中で「:id」を指定されているルーティングで、viewファイル側のリクエスト箇所でも同じように'tweets/:id'としてしまうことである。
【例】
1 |
<%= link_to '削除', '/tweets/:id', method: :delete %> #よくある間違い
|
「:id」は、「ここに指定したいレコードのidを入れる」という意味なので、数値を入れなければいけない。
例えば<%= link to>タグを使って削除ボタンを作成したいとき、tweetsコントローラーのdestroyアクションへのパスが’/tweets/:id’とroutes.rbで設定されていたとすると、以下の例のように書く。
【例】
1 |
<%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
|
ちなみに、#{}は文字列の中でRubyの式を展開するための記号。
③HTTPメソッドは合っているか?
リクエストは、HTTPメソッドとパスで成り立っている。パスの指定は合っていても、HTTPメソッドが違っている可能性がある。
routes.rbに書いてあるHTTPメソッドと、ルーティングをリクエストする箇所で指定しているHTTPメソッドが合っているか確認する。
例えば以下のように、link_toタグを使ってtweetsコントローラーのeditアクションへのルーティングを作成しようとしエラーが出たとする。
【例】
1 |
<%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :delete %> #エラー
|
このような場合は、ターミナルから「rake routes」というコマンドを打ってみる。すると、以下のような表示になる。
【例】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root GET / tweets#index
tweets GET /tweets(.:format) tweets#index
POST /tweets(.:format) tweets#create
new_tweet GET /tweets/new(.:format) tweets#new
edit_tweet GET /tweets/:id/edit(.:format) tweets#edit
tweet PATCH /tweets/:id(.:format) tweets#update
PUT /tweets/:id(.:format) tweets#update
DELETE /tweets/:id(.:format) tweets#destroy
user GET /users/:id(.:format) users#show
|
薄く光っている部分が、tweetsコントローラーのeditアクションへのルーティング。左側にある「GET」というのが、指定すべきHTTPメソッド。
なのでこの場合は、以下のようにHTTPメソッドの指定を書きなおすことで正常に動作する。
【例】
1 |
<%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %> #:deleteを:getに変更することで
|
SyntaxError in [問題箇所のコントローラー]#アクション
エラーの種類
Rubyの文法エラー
SyntaxError
Rubyの文法が間違っている場合に起きるエラー。例えば構文に必要な「end」がなかったり、""(クォーテーション)や「,」(カンマ)忘れなどで良く起こる。
[問題箇所のファイル名]: syntax error, unexpected ・・・end-of-input
【例】
【解決法】 以下の箇所をチェック。
①「end」の数に過不足はないか?
メソッドの中でif文やeach文を利用しているときに、うっかりendを書き忘れていることがある。
問題箇所のファイルの中でendの数が正しいかどうかを確認する。
[問題箇所のファイル名]: syntax error, unexpected unexpected ':', expecting keyword_end
【解決法】 以下の箇所をチェック。
①""(クォーテーションや「,」(カンマ)忘れはないか?
良くあるのが、以下の例のようにlink toタグなどを使うときに「,」を忘れてしまうパターン。
【例】
1 2 |
Template is missing
エラーの種類
Railsのエラー
Template is missing
指定されたviewファイルが無い場合などに起きるエラー。
*Missing template "#コントローラー/アクション名" *
【例】
【解決法】 以下の箇所をチェック。
①リクエストを受け取るアクションに対応したviewファイルがあるか?
例えば、送信したリクエストがtweetsコントローラーのcreateアクションへのものならば、以下の図の通り、
app/views/tweets/以下にcreate.html.erbが必要である。
- app
- views
- tweets
- create.html.erb
- tweets
- views
名前の対応したviewがあるか、また名前の打ち間違いがないか、確認する。
②リダイレクトの処理を書く
アクションに対応するviewファイルがなくても、アクションの処理の最後にリダイレクトを指定していればこのエラーは発生しない。
もしそのアクションをしても固有のviewを出したくない場合は、リダイレクトを指定する。