hiyoko-programingの日記

プログラミングを勉強したてのひよっ子。   エンジニア目指して勉強中。

トラブルシューティング

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 [メソッドを使用されたインスタンス]

【例】

投稿画面

【解決法】 以下の箇所をチェック。

①そのインスタンスのクラスに定義されているメソッドを使用しているか?

以下の例のように、メソッドを使用するインスタンスのクラスに定義されていないメソッドを使用するとエラーになる。

【例】

test.rb
1
2
3
  100.each do |num|   #数字クラスのインスタンスにeachメソッドは定義されていないのでエラーになる
    puts num
  end

メソッドを使用する際は、使用されるインスタンスがどのクラスのインスタンスなのかを意識する。

②メソッドを使用しているインスタンスnilになっていないか?

エラーメッセージの後半が「`[メソッド名]' for nil::nilclass」となっている場合、メソッドを使用しているインスタンスnilになっている。そのインスタンスを生成している箇所を調べてみる。

よくあるのは以下の例のような、部分テンプレートでの「'nickname' for nil::nilclass」エラー。

【例】

ruby_tweet.html.erb
1
  <%= tweet.user.nickname %>    #tweet.userがnilになっているというエラーが出る

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'としてしまうことである。

【例】

test.html.erb
1
<%= link_to '削除', '/tweets/:id', method: :delete %>  #よくある間違い

「:id」は、「ここに指定したいレコードのidを入れる」という意味なので、数値を入れなければいけない。

例えば<%= link to>タグを使って削除ボタンを作成したいとき、tweetsコントローラーのdestroyアクションへのパスが’/tweets/:id’とroutes.rbで設定されていたとすると、以下の例のように書く。

【例】

test.html.erb
1
<%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>

ちなみに、#{}は文字列の中でRubyの式を展開するための記号。

③HTTPメソッドは合っているか?

リクエストは、HTTPメソッドとパスで成り立っている。パスの指定は合っていても、HTTPメソッドが違っている可能性がある。

routes.rbに書いてあるHTTPメソッドと、ルーティングをリクエストする箇所で指定しているHTTPメソッドが合っているか確認する。

例えば以下のように、link_toタグを使ってtweetsコントローラーのeditアクションへのルーティングを作成しようとしエラーが出たとする。

【例】

test.html.erb
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メソッドの指定を書きなおすことで正常に動作する。

【例】

test.html.erb
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タグなどを使うときに「,」を忘れてしまうパターン。

【例】

test.rb
1
2
  <%= link_to 'テスト' "/tweet/" method: :get %>    #「,」が無い
  <%= link_to 'テスト', "/tweet/", method: :get %>  #「,」がある!

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

名前の対応したviewがあるか、また名前の打ち間違いがないか、確認する。

②リダイレクトの処理を書く

アクションに対応するviewファイルがなくても、アクションの処理の最後にリダイレクトを指定していればこのエラーは発生しない。

もしそのアクションをしても固有のviewを出したくない場合は、リダイレクトを指定する。