LoginSignup
1
1

More than 5 years have passed since last update.

もそ、プログラミングを学ぶ【Ruby & Rails復習編】〜コントローラのエラーを解いてみよう!〜

Last updated at Posted at 2019-04-17

Rubyのおさらいをしながら、エラー問題にチャレンジ中の もそ。
少しずつではありますが、今まで理解できていなかった部分がわかるようになってきました。

今日は実際のエラー画面を見ながらコードの解説をしていきます。

謎のエラー発生!

まずは実際のエラー画面がこちら。↓

9ce11ce809aa03a3cc9f7298d360f985.png

トップ画面から詳細画面を開こうとしたところ、このようなエラーが出てしまいました。
いきなりこの画面が出てくるとなかなか面食らいますよね...
でも冷静に読み解いていけば、どんなエラーが起きているか簡単に目星をつけられます。

画面やコードを見ながら、一緒にエラーの謎を暴いていきましょう!

エラー解決編

エラーを解決するためには、

①エラーを起こしているファイルを特定
②ファイル内の記述を確認、まちがっている場所を見つける
③正しい記述に修正する

この3ステップが必要です。

まずは①"エラーが起こっているファイルを特定"します。
なんだか探偵になった気分ですね!

先ほどのエラー画面をもう一度見てみましょう。
赤いボックス内に「NoMethodError in TweetsController#show」と書いてあります。
これを読み解くと、「TweetsControllerのshowアクションでメソッドが定義されていないエラーが起きている」という意味になります。

無題1172.jpeg

このTweetsController、めっちゃ怪しいですよね。
まずこの時点でtweets_controller.rbファイルがどうも怪しいぞ...と、探偵もそ(いま命名しました)は気づきます。

次に②"ファイル内の記述を確認、まちがっている場所を見つけ"ます。

先ほどのエラー画面では「なんやTweetsControllerのshowアクションでエラーが起きてるみたいやで」と証言しています。
なのでtweets_controller.rbファイルを開いて、showアクションに関する記述の部分を調べてみることにしました。


    def show
      @comments = @tweet.comments.includes(:user)
    end

うーん。

...ん?

なんか記述少なくね?

と気づけたそこのあなた、もう謎(エラー)を解いたも同然です。
このshowアクションでは「tweetの詳細ページとcommentsを出す」という動きを指示しています。
でもこのままの記述だと肝心のtweetがすっぽり抜け落ちています。

つまり正解は...

    def show
      @tweet = Tweet.find(params[:id])
      @comments = @tweet.comments.includes(:user)
   end

@ tweet = Tweet.find(params[:id])という一文が失踪していたことによるエラーということが分かり、このエラーは一件落着。

ところで抜けていたコードの中身はどんな記述かというと、
tweetsテーブルの中にある@ tweetというインスタンス変数を、Tweetモデルがparams[:id]というハッシュの箱に入れてコントローラに渡しています。

paramsについてはこちらも参考にしてみてください。

コントローラとモデル、アソシエーション

ここで、コントローラとモデルのおさらいをしてみましょう。

    def show
      @tweet = Tweet.find(params[:id])
      @comments = @tweet.comments.includes(:user)
   end

先ほどのコードを見た時、
「@ commentsの:userにはモデルを指定しなくていいの?」
という疑問があるかもしれません。

なぜモデルを指定しなくていいかというと、TweetモデルとUserモデルはアソシエーションをしているからなんです。
下の図を見てください。

無題1140.jpeg

ここではコントローラがTweetモデルとUserモデルそれぞれにDBの中身を渡してくれ、と指示をしています。

2つのモデルそれぞれに動いてもらってDBの中身を渡してもらおうとすると、Tweetモデルに指示を出してデータを渡してもらって、Userモデルにもデータを渡してもらって...という処理が発生します。
モデルがたくさんある場合だと、それぞれのモデルを呼び出さないといけないため処理が重くなってしまいます。

そこでアソシエーションをして、モデルとモデルを結びつけておきます。
そうすると、あるモデルが呼び出された時に紐付いたほかのモデル配下のデータも引き出せるというわけです。

今回の例だと、

 @tweet = Tweet.find(params[:id])
 @comments = @tweet.comments.includes(:user)

Tweetモデルが呼び出されたときに、@ commentsのuserも呼び出せるようになっていました。

ひとつのtweetに対しては複数のコメントがつきます。
そしてコメントには、必ず一人のユーザーがいます。

これを1対多の関係と呼びます。
この関係を定義しておくことで、一つの情報から芋づる式に情報を受け取ることができます。

--

まだぱっとコードを記述するまでには至らないものの、コードの中身が何を指しているかは何となくわかってきました。
これは私にとってかなりの大進歩です...!
この調子で勉強しつつ、プログラミングに覚醒するXデーを待つ もそであった...続く。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1