chat-space 非同期化

## この実装のゴール
chat-spaceの非同期化を完成させる。


##  流れ
⑴ jsファイルの作成する
⑵ フォーム送信後、イベント発火
⑶ イベント発火後、Ajaxを使用して、createアクションの始動
⑷ createアクションでメッセージを保存し、respond_toを使用してHTMLとJSONで処理を分ける
⑸ jbuilderを使用。作成したメッセージをJSON形式で返す
⑹返ってきたJSONを受取り、HTMLの作成する
⑺ 6で作成したHTMLを画面に追加する
⑻ メッセージを送信したとき、最下部にスクロールする
⑼ 連続で送信ボタンを押せるようにする
⑽ 非同期に失敗した場合の処理も準備する

## ⑴ jsファイルの作成する
message.jsを作成　(app/assets/javascriptディレクトリ)
→jsの処理を記載するファイル


## ⑵ フォーム送信後、イベント発火
```message.js

$(function(){ //これは決まり

//new_messageクラスで送信ボタンが押された時の処理を書くよ
  $('.new_message').on('submit', function(e){   

//デフォルトのイベント停止（フォーム送信の停止)
  e.preventDefault(); 

  })
})

```

## ⑶ イベント発火後、Ajaxを使用して、createアクションの始動

```message.js

//ここから
$('.new_message').on('submit', function(e){
  e.preventDefault();
//ここまでは上記

//thisでイベントが起こったところを特定し、そこのフォームデータを取得後、変数ｆｏｒｍDataに代入
  let formData = new FormData(this); 

//フォームの送信先urlを自動取得し変数urlに代入
  let url = $(this).attr('action')

  $.ajax({ //決まり
    url: url, //上で定義
    type: "POST", //HTTPメソッド(今回はcreateアクションに送るので)
    data: formData, //上で定義
    dataType: 'json', //json形式で送る
    processData: false, //この辺は決まり
    contentType: false //この辺は決まり
  })

```
## ⑷ createアクションでメッセージを保存し、respond_toを使用してHTMLとJSONで処理を分ける

```messages_controller.rb

#createアクションの編集
def create

#メッセージを取得し、@messageに代入(過去のカリキュラム)
    @message = @group.messages.new(message_params)

#@messageが保存されたら
    if @message.save
#htmlとjsonの分岐
      respond_to do |format|
        format.html { redirect_to "group_messages_path(params[:group_id])" }
        format.json
      end  
#保存されなかったら
    else
#処理を記述
    end
end

```

## ⑸ jbuilderを使用。作成したメッセージをJSON形式で返す

```create.json.jbuilder

#createコントローラー内で定義した変数を使い、js用に変換しておく　（このあと使います)
json.id      @message.id
json.content @message.content 
json.date    @message.created_at.strftime("%Y/%m/%d %H:%M")
json.user_name @message.user.name
json.image   @message.image.url

```

## ⑹ 返ってきたJSONを受取り、HTMLの作成する
```message.js

//ajax処理の直後に記入

//成功した時の処理を記述(フォームに入力された内容"data"を引数にする)
.done(function(data){

//そのデータを元にhtmlを作成する、処理の呼び出し(処理の詳細は後ほど)
    buildHTML(data);

  })

```

## ⑺ 作成したHTMLを画面に追加する
```message.js

//各自定義しているクラスと異なる場合があるので注意

//htmlを作るよっていう関数
function buildHTML(message){

//画像データがある時とない時で処理を分け、変数imageに代入
    image = ( message.image ) ? `<img class= "lower-message__image" src=${message.image} >` : "";

//ここからはhtmlを記述し変数htmlに代入。jbuilderで定義した変数はここで使われる
    let html = `<div class=message>
                    <div class="upper-message">
                      <div class="upper-message__user-name">
                      ${message.user_name}　
                      </div>
                      <div class="upper-message__date">
                      ${message.date}
                      </div>
                    </div>
                    <div class="lower-message">
                      <p class="lower-message__content">
                      ${message.content}
                      </p>
                      ${image}
                    </div>
                  </div> `

//作ったhtmlをmessagesクラスにぶち込む
    $('.messages').append(html); 
  }

```

## ⑻ メッセージを送信したとき、最下部にスクロールする

```message.js
    
.done(function(data){
    buildHTML(data);   

//animateメソッドを使い自動スクロールを設定 
    $('.messages').animate({scrollTop: $('.messages')[0].scrollHeight}, 'fast');   

//入力欄の値をリセットにする    
    $('form')[0].reset();
  })

```

## ⑼ 連続で送信ボタンを押せるようにする
```message.js

//$('.new_message').on('submit', function(e){　の処理の最後に
return false;
//と記述


```

## ⑽ 非同期に失敗した場合の処理も準備する
```message.js

//doneの処理の後に記述(失敗した時という意味)
.fail(function(){
      alert('error');
    });


```