Rails初学者に知ってほしいこと

# はじめに
初めまして:exclamation:
<font color="MediumOrchid">DMM WEBCAMP mentor Advent Calendar 2023</font> :christmas_tree: 17日目を担当します@y-428です:exclamation:

Qiita初執筆ということで、誤字・脱字や分かりにくい表現など、至らぬ点もあるとは思いますがどうか温かい目で見守っていただければと思います:bow:

そんな私が今回取り上げたいのは<font color="LightCoral">Rails初学者へ向けた知識</font>となっています。

これは主に、<font color="LightCoral">エラー解決ができなくて挫折してしまっている方</font>をターゲットとしていますので、これに当てはまっている方はもちろんのこと、他にもRailsを学び始めた方、Railsを教える立場にある方などなど、少しでも読んで楽しんでいただけたらなと思います。

では早速やっていきましょう:exclamation:

# 変数とは
記念すべき最初に押さえておいてほしい知識として紹介するのは<font color="Red">変数</font>についてです:exclamation:

変数はRailsというよりかは、このフレームワークで使用しているプログラミング言語の`ruby`の話にはなるのですが、実際こいつをうまく使えないと本当に苦労します:exclamation:
ですので、ここ基礎を理解し、落とし込んでいただけたらと思います～:exclamation:

まずはじめにこの記事を読んでいただいている方は「変数」と聞くとどのようなイメージが浮かぶでしょうか。:thinking:
初学者の方は変数と聞くと、中学校や高校の数学で習ったものが浮かんでくるかもしれませんね。
まあつまり中身が分からない数みたいな感じになると思います。(xとかyとかですね～)
それもあながち間違いではないのですが、ここで覚えていただきたいことは一つだけです:exclamation:

変数はただの入れ物:package:だということです。

そう、変数というのはざっくり言ってしまえば値を一時的に保持しておいてくれる便利な入れ物のことなんですね～。
つまり、あとで使おうと思ってる値を変数に渡しておくだけで、その変数を呼び出してあげれば中身も使えますよ～って話です。

また、変数名についても聞かれることがよくありますのでここで答えておきますが、結論変数名は<font color="Red">何でもいい</font>です。
まあ実際は各々の会社や現場によって命名規則が設けられていたりするかもしれませんが、名前によって何かが変わるということはないです。

ただ言えることとしては、他人が見たときに分かりやすいようにしときましょうね～ぐらいです:exclamation:

# MVCアーキテクチャ
この章ではMVCアーキテクチャについて話していきます。

Railsの学習を始めるとMVCという言葉をよく耳にすると思います。
これはそれぞれ `M(Model)` `V(View)` `C(Controller)` の頭文字をとったもので、これらがRailsを学ぶ上での基礎中の基礎、根幹部分にあたります。
これが理解できていないと、**Railsではなにもできない**と言っても過言ではありません。

ではMVCについて軽く解説していきます:exclamation:

<dl>
    <dt>Model</dt>
    <ul>
        <li>Modelは、RailsアプリケーションがDB(データべース)とやりとりを行うためのものです。</li>
        <dd>こいつがいてくれないとデータの保存ができず、やりたいことの幅が非常に狭まってしまいます。
        </dd>
        <li>DBとのやりとりが行えると捗ること</li>
        <dd>
            <ul>
                <li>データの保存</li>
                　何かの新規投稿だったり、新規作成だったりの機能のために必要になります。
                <li>保存したデータの呼び出し</li>
                　上記で作成したデータを表示させたりする機能の実装に必要になります。
            </ul>
        </dd>
    </ul>
    <dd>まあ要はControllerとDBの橋渡し役になってくれててるわけですね、感謝しておきましょう。:pray::pray::pray:</dd>
</dl>

<dl>
    <dt>View</dt>
    <ul>
        <li>Viewは実際にアプリケーションを使用しているユーザの目に入る部分のデータを扱っています。</li>
        <ul>
            <li>イメージ的にはユーザはViewページが直接ブラウザなどで見えているみたいな感じですね。</li>
        <li>一応厳密に説明すると、RailsアプリケーションがControllerに対して「特定のViewページを読んでくれ～:exclamation:」という指示を出すと、そのViewページに対応するアクションが起動してViewページを呼び出し、HTML文書を作成してユーザが見ているブラウザなどに返しているわけですね。</li>
        </ul>
        <li>ここで押さえておいてほしいのは、「Viewページには対応するアクションがある」ということです:exclamation:</li>
        <ul>
            <li>ここさえ押さえておけば初学者としてはばっちりです:exclamation:（多分）</li>
            <li>というのも、原則Viewページはアクションがないとそもそも呼び出せないからですね。</li>
        </ul>
    </ul>
    <dd></dd>
</dl>
<dl>
    <dt>Controller</dt>
    <dd>ここでは以下の２点について話していきます。</dd>
    <dd>
        <ul>
            <li>アクション</li>
            <dd>まずはアクションについてです。<br>
            こいつはさっきのViewのとこでもちょろっと出てきましたが、具体的にはなにをしてくれる奴なのか詳しく話していきますね :grinning:</dd>
            <dd>
                <ul>
                    <li>アクションというのはControllerの中で定義されるもので、中身には特定の処理内容が記述されています。</li>
                    <li>例えば、<code>データの保存や更新の処理</code>だったり、 <code>データの削除処理</code>とかだったりですね。</li>
                    <li>変数の定義についても、アクション内で基本行います:exclamation:</li>
                </ul>
            </dd>
            <li>Routing</li>
            <dd>ではRoutingについて話していきます。</dd>
            <dd>Routingはそのまま翻訳すると道や経路といった言葉になります。</dd>
            <dd>Railsアプリケーションにおいてもこの意味で使われており、あるURLと特定のコントローラの特定のアクションへの道を示す(結びつける)ために定義されます。</dd>
            <dd>イメージ的にはそのアクションへの住所:mailbox:に近い感じです。</dd>
            <br>
            <dd>Railsアプリケーションは。ユーザがアクセスしたURLから紐づいたアクションを呼び出しているといった流れになります:exclamation:</dd>
        </ul>
    </dd>
</dl>

この3つ(MVC)について話したところで結局何を言いたかったかというと、どれが何の役割を担っているかをざっくりとでもいいので知っておいて欲しいよ～:exclamation:ってことです。

道(Routing)がなければControllerからアクションは起動できないですし、アクションが起動しなければViewも呼び出せません。

エラー解決の原因を探る上でもどれが何をしているかは絶対に理解しておくべきです:exclamation:
全部は覚えなくてもいいので、役割だけでも覚えておきましょう。

# NoMethodErrorの対応の仕方 
この章では、`NoMethodError` について話していきます。

このエラーはとても頻発し、なおかつシンプルな原因で起きているにもかかわらず、「どうやって解決していけばいいか分からない」という方が非常に多いため、少しでも参考になればと思い書くことにしました。
エラーの見つけ方や解決の仕方までの、基礎的な部分を話せたらなと思いますのでよろしくお願いします:exclamation:

一応この章で出てくるアプリケーションの概要について話します。
このアプリケーションは自分が読んだ本のタイトルとあらすじを投稿するという簡単なサイトで、実装している機能は`本の投稿` `投稿された本の一覧表示` `投稿した本の詳細表示` `投稿した本の編集` `投稿した本の削除` の5つです。

`Book`モデルを作成し、タイトルとあらすじを格納するカラム`:title` `:body` を追加しました。

``` create_books.rb
class CreateBooks < ActiveRecord::Migration[6.1]
  def change
    create_table :books do |t|
      t.string :title
      t.text :body
      t.timestamps
    end
  end
end
```

ではどんどんやっていきましょう。

- どういうときに発生するのか
    まずはどういったときにこのエラーが発生するかについてですね。
    実際のエラー文を見ていただきましょう。
    状況としては `投稿した本の一覧画面` から `投稿した本の詳細画面` へ遷移するURLを押した後に出てきたエラーになります。
    - 1つ目
    ![NoMethodError_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583310/1123d20f-b7a5-8d27-4b60-17bb78beb74f.png)
    - 2つ目
    ![NoMethodError_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583310/6a76eb40-cb40-bc80-17bb-2f8033280780.png)


エラー画像が1枚だけだと思った方は要注意です。

これはそれぞれ違う事が原因でエラーを引き起こしているのですが。どちらも`NoMethodError` が吐かれていますね。
まあ大体のエラーがそうなのですが、原因が一つしかないなんてことは基本あり得ません。
初歩的なエラーであるNoMehodErrorでも、既に2つ以上原因になりうるものがあることが確定しましたね、、
他にも様々なことが原因でこのエラーが吐き出されますが、一先ずその中でも頻出する原因について話していきます。

- 原因は何か
    では原因について話す前に、エラーとはそもそもなぜ発生するのでしょうか。
    それはつまり、「記述した処理に対してこのままじゃうまく実行できませんよ～」という状態になってしまっているからです。
    少し詳しい話をすると、そもそもViewページの表示はコンピュータがコードを解読(コンパイルと言います)することによって最終的にブラウザに表示されます。
    ではその解読作業でコンピュータが解読できないものがあるとどうなりますか？
    はい、これがエラーです:exclamation:

    つまりエラーの解決というのは、コンピュータがコードを解読できるようにすればいいってことになります。

    では次からどうやってエラーの原因を探すのか等についてお話しできればと思います。
    <br>
    
- 原因(1)
    ではまず1枚目のエラーについて、まずはこの記事を読んでいただいている方は何が原因だと思いますか？
    「titleメソッドが未定義」だと思ったあなた、、、ありがとうございます(?)
    まあ出ているエラー文`undefind method 'title'`を訳するとそうなりますよね、、、
    確かに言われていることは間違ってません。ですが、titleメソッドが未定義というのはエラーの原因ではありません。
    このエラーで注目しないといけないのはforから後の部分になります。
    1枚目のエラーは`nil:Nilclass` となっています。
    - nil:Nilclass
        これはざっくり言うと中身が入ってない、空になってますよ～っていう意味です。
        
    下記がプログラムが止まってしまった場所なのですが
    
    ``` show.html.erb
        <div><%= @book.title %></div>
    ```

    この`nil:Nilclass` がエラー画面で表示された際のエラーの意味としては
    「空の変数に対してメソッドが実行されていますよ」とするのが正しいです。
    もっと簡単に言うと、「変数`@book` の中に何も入ってないので`title`メソッドが実行できません」ということになります。

    - 解決方法
        では具体的にどうすれば解決できるのか、、、
        変数に中身が無いからエラーが起きるということは、中身があればいいんですよね？
        先程のMVCの章で、変数はアクションで定義しますと私は書きました。
        つまり見てあげないといけないのは、「該当アクションで変数が定義されているかどうか」ということになります。
        今回は`Books#show` で発生しているので、`bookscontroller.rb` を見に行きましょう。

        どうなっているかというと、、

        ``` booscontroller.rb
        class BooksController < ApplicationController
            ~~~~~ 省略 ~~~~~

            def show
            end
            
            ~~~~~ 省略 ~~~~~
        end
        ```

        はい、アクションはあるのに中身には何も記述がありませんよね。
        このままではviewページで`@book` を使用しても、中には何も入ってないので、そりゃエラーも出ちゃいますよね:sweat_smile:
        なので、変数をアクションでしっかりと定義してあげましょう。
        
        今回はshowページ、つまりある特定の本の中身を`@book` に入れてあげればいいので
         ``` booscontroller.rb
         class BooksController < ApplicationController
            ~~~~~ 省略 ~~~~~

            def show
                @book = Book.find(params[:id])
            end
            
            ~~~~~ 省略 ~~~~~
        end
        ```
        となりますね。

        これで`@book` の中身がしっかりと入っているので、viewページが表示できるようになります！
        <br>

- 原因(2)
    では2枚目のエラーについても話していきます。
    このエラーでまず見ないといけなかったのではどこでしたっけ、、、？

    そう、エラー文の`for` より後ろでしたね～。
    今回は`nil:Nilclass` ではなく何やらいろいろ書かれていますね。
    中身をしっかり見ていくと、`#<Book id:4, title:"こころ", body:"私と先生が...(省略)">` と書かれており、Bookモデルがしっかりと変数には格納されているということが分かります。

    つまり今回のエラーの原因は「変数は渡せているのにメソッドが実行できていない」ということになります。

    こういった場合は、「本当に未定義のメソッドを呼んでいる」や、「スペルミスが発生している」などが考えられます。
    エラー文をもう一度確認してみると、今回は`undefined methoid 'titl'` と書かれていますね。
    今回タイトルを格納するカラムとして作ったのは`title` カラムです。

    つまり原因は呼び出すメソッド名を間違えてしまっているからです。
    この場合は直訳の「titlメソッドは未定義」という意味があっていますね:grinning:
    
    - 解決方法
        わざわざ解決法として項目を用意しましたが、2つ目に関しては正しいメソッドを呼んであげるだけの簡単なものですね。
        なので詳しくは書きませんが、viewページでしっかりと`title` を呼んであげればOKです:exclamationです:exclamation::

とまあ`NoMethodError` について触れていきましたが、意外と解決までに見ているところなんかはシンプルですよね。

なんでもそうですが、基本的にはエラー文にすべてが詰まっています。
まずはエラー文を読んでみて、間違っててもいいので何がダメと言われているかを考えることがエラー解決への第一歩になります。
エラー文がわからないままでは絶対に解決できませんからね。

つまりここで言いたいことは1つだけ、エラー文を絶対に読んでください:exclamation:

# ターミナルの見方

この章からは、ターミナルの見方についてさくっと話していこうと思います。

Railsを勉強しているとよくターミナルを見ろと言われると思いますが、正直そんなこと言われても何を見ればいいのか分かりませんし、見ても何の事やら分かりませんよね:sob:
なのでとりあえず「どこを見てほしいか」、「それが何の意味を表しているか」について簡単に話せたらと思います。

一先ず今回紹介する知識さえあれば一旦は大丈夫なはずです、、(多分)

先程の章で使ったアプリケーションを今回でも使って解説していきます:exclamation:

とりあえず例として1つ出します。
状況はBooks#indexに遷移したときです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583310/76533e61-d2af-7f54-9e37-074c73ca3f97.png)

- アクションの切り替わり
    ターミナルにはいろいろ出てますが、とりあえず2行くらい間隔があいている箇所。
    間隔の大きさは環境にもよりますが、ここがアクションが切り替わったことを表しています。
    そして一番最初の行に、どのURLが、どのHTTPメソッドで呼び出されたかが出力されます。
    今回は`/books` が`GET`メソッドで呼びだされていますね。
    
    そして2行目の`processing by ...` となっている部分ですが、これはユーザがアクセスしたURLに、Routingで紐づけされたコントローラおよびアクションを起動したことを表しています。
    今回は`BooksController` の`index`アクションがきちんと呼び出されていますね。

    アクションの切り替わりに関してはこの2つの出力さえ見れれば大丈夫です。
<br>

- DB(データベース)に関わるコードが実行された
    何やらターミナルにはいろいろ書かれていますが、色が変わっている箇所がありますよね。
    これも環境によっては色が青じゃなかったりなどはあるのですが、私の環境は水色っぽい青になっている所。
    これが、DBに関わる処理がされた証拠になります。
    今回でいうと `Book Load` と出ていますのでDBから何か参照してくるような記述があったということになります。
    例えば`Book.all` だったり`Book.find` だったり、、、
    その判別は後ろの`SELECT "books" ...` となっている所でできますが、初学者の方はここまでは覚えようとしなくても大丈夫です！
    とにかくDBに触れたんだなということがわかるようになってほしいです:exclamation:
    - ちなみに今回はモデル名が`Book` なだから先頭に`Book ~~`　とくるようになっているだけなので、ここはモデル名によって変わっていきます:exclamation:

    ほかにも`save` などのDBに新たにレコードを追加するようなメソッドが実行されると
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583310/c0ae1bb9-2d5f-a567-ce04-01bff9fee09d.png)
    このような出力がされます。
    
    実際に保存処理をしているのは`Book Create` と出力されている箇所ですね。
    これがわかっていると例えば新規投稿機能でエラーが出て詰まってしまったとき、それは`save` が実行される前なのか、後なのか、という判断をターミナルからでき、原因の追究がしやすくなりますよね。

    ちなみにレコードの更新を行う`update`メソッドが実行されると`Book Update`、レコードの削除を行う`destroy`メソッドが実行されると`Book Destroy` という文章が出力されます。(一応下にターミナルの画像を載っけておきます)
    - update
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583310/cbd911af-ba3b-e5ee-f2c6-58d4aa0c3e14.png)
    - destroy
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583310/eb4fd08d-54a4-06c2-2824-9c535ffe686c.png)

    このDBへの関与がターミナルから読み取れるようになるだけで、エラー解決や機能の実装の効率が段違いに変わってくるので、この辺は絶対に押さえておいてほしいです:exclamation:

- リダイレクトしたとき
    さいごにリダイレクトしたときについても話していきます。
    これはつまり、アクションの最後に`redirect_to` など、別のアクションへ遷移するような記述があったときに出力されます。
    つまり`GET` 以外のHTTPメソッドのアクションでよく見られるということですね。
    なぜかというと、`GET`メソッドはそもそもviewページを取得するメソッドの時に使われるため、特に何もしなくてもそのアクションが起動すれば、それに対応するviewページが呼び出されます。
    しかし、`POST` `PATCH` `DELETE` のようなHTTYPメソッドは通常viewページを持たず何かの処理のために使われることが多いです。
    そのためリダイレクト無しで処理を終えると、アクションが遷移せず、viewもそのままといったように、アプリケーションの処理が止まってしまいます。

    なので、そういったアクションには`redirect_to` のようなメソッドを用いてviewページを持つアクションに遷移しているわけですね。
    ターミナルでいうと、`save(POST)` `update(PATCH)` `destroy(DELETE)`の下から2行目の`Redirected to
` と書かれている部分。
    これが、このアクションでの処理が終了し、次のアクションへ遷移しているという証拠になります。

# おわりに

ここまで読んでいただいた方、本当に感謝しかないです。

つらつらと長い文章だけになってしまうところなどもあり、皆さんのお役に立てたかは分かりませんが、もしお役に立つことがあったのなら幸いです:sob:

なかなかエラー解決ができなくて挫折してしまう方が多いのがプログラミングの学習の怖いところだとは思いますので、めげずにこれからも頑張っていきましょう:exclamation:

ではこの記事の終了とさせていただきますので、もしまた私が記事を書くようなことがあれば、どうぞよろしくお願いいたします:bow:
御精読ありがとうございました:exclamation: