js→railsへのajax通信で404エラーを出しまくった話。

#はじめに
はい皆の衆よくお聞き
初心者様による
初心者でもできるエラー殺し講座を始める

**よく聞かないと死にます**

#背景
前回、[ancestryとjQueryで多階層型カテゴリの入力フォームを段階的に表示させてみた](https://qiita.com/0thefool/items/6de6bcca6dc4e4f174c1)を投稿するためにサンプルを作ったのですが、さすが初心者。
サンプルを作り終える間に多大なエラーを出しては修正し、修正しては出ししていました。
今回はそのエラーから「４０４ NotFound」を切り出して、どのように解決していったかを記事にしていきます。

#今回取り扱うエラーについて
**404 (Not Found)**
HTTP 404、またはエラーメッセージ Not Found（「未検出」「見つかりません」の意）は、HTTPステータスコードの一つ。 クライアントがサーバに接続できたものの、クライアントの要求に該当するもの (ウェブページ等) をサーバが見つけられなかったことを示すもの。(wikipediaより抜粋)

#第一の404 (Not Found）
まず、「js書くべし」で以下のjsを書きました。

```assets/javascript/items.js
$(function() {
  function buildHTML(result){
    var html =
      `<option value= ${result.id}>${result.name}</option>`
    return html
  }

  $("#parent").on("change",function(){
    var int = document.getElementById("parent").value
    if(int == 0){
      $('#child').remove();
      $('#item_category_id').remove();
    }else{
      $.ajax({
        url: "categories/",
        type: 'GET',
        dataType: 'json',
        data: {id: int}
      })
      .done(function(categories) {
        var insertHTML = `<select name="child" id="child">
                          <option value=0>---</option>`;
        $.each(categories, function(i, category) {
          insertHTML += buildHTML(category)
        });
        insertHTML += `</select>`
        if($('#child').length){
          $('#child').replaceWith(insertHTML);
          $('#item_category_id').remove();
        } else {
          $('.items__child').append(insertHTML);
        };
      })
      .fail(function() {
      });
    };
  });
})
```

はい、もーなんか既に分かる人には分かりますね。

これで親の選択フォームを変更するとエラーになります。
![スクリーンショット 2020-03-14 15.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600698/8befdc83-783e-92a7-4d9a-a3e7db8e11a0.png)

###原因
原因はこれでした。
`url: "categories/",`
以下のように変更しました。
`url: "categories/",` => `url: "/categories",`

####気付いたきっかけ
ターミナルを見た時に以下のようになっていました。
`Started GET "/items/categories/?id=1" for ::1 at 2020-03-14 15:17:23 +0900 
ActionController::RoutingError (No route matches [GET] "/items/categories"):`

**？なんでitemにネストしたurlになってるの？**
ということで、ネストしないようにurl修正しました。

#第二の404 (Not Found）
しかし、再度親の選択フォームを変更するとエラーになります。
![スクリーンショット 2020-03-14 15.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600698/8befdc83-783e-92a7-4d9a-a3e7db8e11a0.png)

今度のターミナルエラーはこれ。
`Started GET "/categories?id=1" for ::1 at 2020-03-14 15:36:36 +0900
ActionController::RoutingError (No route matches [GET] "/categories"):`

###原因
ただのroutingの設定忘れでした。

```config/routes.rb
Rails.application.routes.draw do
  root "items#new"
  resources :items ,only: [:index,:new,:create]
end
```
修正します。

```config/routes.rb
Rails.application.routes.draw do
  root "items#new"
  resources :items ,only: [:index,:new,:create]
  resources :categories ,only: :index
end
```

#第三の404 (Not Found）
しかし、再度親の選択フォームを変更するとエラーになります。
![スクリーンショット 2020-03-14 15.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600698/8befdc83-783e-92a7-4d9a-a3e7db8e11a0.png)

ターミナルエラーはこれ。
`Started GET "/categories?id=1" for ::1 at 2020-03-14 15:45:21 +0900
ActionController::RoutingError (uninitialized constant CategoriesController):`

###原因
categories_controller.rbが無い・・・だと？
ちゃんとあるじゃ・・・ある・・・あ？
![スクリーンショット 2020-03-14 16.00.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600698/2d6f4ab8-a0a9-f5d8-bd93-69812c33e6ab.png)


```/controllers/category_controller.rb
class CategoryController < ApplicationController
  def index
    @categories = Category.where(ancestry: params[:id])
    respond_to do |format|
      format.json
    end
  end
end
```
・・・controller作る時に単数形にしてますね・・・。
消して作り直します。

```terminal.
$ rails d controller category
$ rails g controller categories
```
```/controllers/categories_controller.rb
class CategoriesController < ApplicationController
  def index
    @categories = Category.where(ancestry: params[:id])
    respond_to do |format|
      format.json
    end
  end
end
```
#結果
**ちゃんと動作するようになりました！**
![スクリーンショット 2020-03-14 15.54.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600698/43b20b8a-1d41-893e-c156-ef4f1174d6ed.png)

#今回の教訓
**①エラーが出たらターミナルをよく見よう。**
**②routingはちゃんとやっておこう。**
**③controllerは複数形で作ろう。**

今回は以上です。