エラー解決　 Javascript　非同期通信によるメッセージの自動更新機能の実装

javascriptのエラー解決に苦心したので、その記録。

###状況

チャットアプリのメッセージ機能の更新を非同期通信上で、実施しようとしたところ、
投稿まで非同期で通信できなくなった。


```js:問題のjsファイル
(function(){
  var buildHTML = function(message){
    console.log(message)
    if (message.image){
      console('1')
      var html =  
        `<div class = "message" data-message-id=${message.id}>
        <div class="messages__message" >
          <div class="messages__message__info">
            <div class="messages__message__info__member">
              ${message.user_name}
            </div>
            <div class="messages__message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="messages__message__text">
            <p class="messages__message__text__content">
              ${message.content}
            </p>
          </div>
          <img src=${message.image} >
        </div>`
        return html;
    } else {
      console.log('2')
      var html =
        `<div class = "message" data-message-id=${message.id}>
        <div class="messages__message" >
          <div class="messages__message__info">
            <div class="messages__message__info__member">
              ${message.user_name}
            </div>
            <div class="messages__message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="messages__message__text">
            <p class="messages__message__text__content">
              ${message.content}
          </p>
        </div>`
        return html;
    };
  }

    $('.new_message').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);
    var url = $(this).attr('action')
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: 'json',
      processData: false,
      contentType: false
    })
    .done(function(data){
      console.log(data)
      var html = buildHTML(data);
      $('.middle').append(html);
      $('form')[0].reset();
      $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight},'fast');
      $('input').prop('disabled', false);
    })
    .fail(function(){
      alert('メッセージ送信に失敗しました');
    })
  })
  
  var reloadMessages = function() {
    //カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
    last_message_id = $('.message:last').data("message-id");
    $.ajax({
      //ルーティングで設定した通りのURLを指定
      url: "api/messages",
      //ルーティングで設定した通りhttpメソッドをgetに指定
      type: 'get',
      dataType: 'json',
      //dataオプションでリクエストに値を含める
      data: {id: last_message_id}
    })
    .done(function(messages) {
      console.log(messages)
      if (messages.length !== 0) {
        //追加するHTMLの入れ物を作る
        var insertHTML = '';
        //配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
        $.each(messages, function(i, message) {
          insertHTML += buildHTML(message)
        });
        //メッセージが入ったHTMLに、入れ物ごと追加
        $('.middle').append(insertHTML);
        $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight});
        $("#new_message")[0].reset();
        $(".form__submit").prop("disabled", false);
      }
    })
    .fail(function() {
      console.log('error');
    });
  };
  if (document.location.href.match(/\/groups\/\d+\/messages/)) {
    setInterval(reloadMessages, 7000);
  }
});
```

```haml:関連するhamlファイル
.messages
  .messages__message
    .messages__message__info
      .messages__message__info__member
        = message.user.name
      .messages__message__info__date
        = message.created_at.strftime("%Y年%m月%d日 %H時%M分")
    .messages__message__text
      - if message.content.present?
        %p.messages__message__text__content
          = message.content
      = image_tag message.image.url, class: 'lower-message__image' if message.image.present?
```

問題解決までの変更点は以下のとおり。
1.　jsファイル、"buildHTML"内で定義されたhtmlにreturn html;を2箇所追記する。（エラーの解決にはこれだけでよかった気もする...）
2.　hamlファイルから".message"のクラスを削除、hamlファイルとscssファイルをそれに合わせて調整する。
3.　そのままでは自動更新された文にcssが当たらないので、"div class="messages__message" "の記述を削除する。（本来は閉じタグも消去しなければいけないが、記述ミスで上記コードには表記されていなかった）
4.　.done内の".message"でクラス指定されている部分のクラスを指定し直す。

変更後のコードは以下

```js:jsファイル
$(function(){
  var buildHTML = function(message){
    if (message.image){
      var html =  
        `<div class = "message" data-message-id=${message.id}>
          <div class="message__info">
            <div class="message__info__member">
              ${message.user_name}
            </div>
            <div class="message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="message__text">
            <p class="message__text__content">
              ${message.content}
            </p>
          </div>
          <img src=${message.image} >
        </div>`
        return html;
    } else {
      var html =
        `<div class = "message" data-message-id=${message.id}>
          <div class="message__info">
            <div class="message__info__member">
              ${message.user_name}
            </div>
            <div class="message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="message__text">
            <p class="message__text__content">
              ${message.content}
            </p>
        </div>`
        return html;
    };
  }

    $('.new_message').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);
    var url = $(this).attr('action')
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: 'json',
      processData: false,
      contentType: false
    })
    .done(function(data){
      var html = buildHTML(data);
      $('.middle').append(html);
      $('form')[0].reset();
      $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight},'fast');
      $('input').prop('disabled', false);
    })
    .fail(function(){
      alert('メッセージ送信に失敗しました');
    })
  })
  
  var reloadMessages = function() {
    //カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
    last_message_id = $('.message:last').data("message-id");
    $.ajax({
      //ルーティングで設定した通りのURLを指定
      url: "api/messages",
      //ルーティングで設定した通りhttpメソッドをgetに指定
      type: 'get',
      dataType: 'json',
      //dataオプションでリクエストに値を含める
      data: {id: last_message_id}
    })
    .done(function(messages) {
      if (messages.length !== 0) {
        //追加するHTMLの入れ物を作る
        var insertHTML = '';
        //配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
        $.each(messages, function(i, message) {
          insertHTML += buildHTML(message)
        });
        //メッセージが入ったHTMLに、入れ物ごと追加
        $('.middle').append(insertHTML);
        $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight});
        $("#new_message")[0].reset();
        $(".form__submit").prop("disabled", false);
      }
    })
    .fail(function() {
      console.log('error');
    });
  };
  if (document.location.href.match(/\/groups\/\d+\/messages/)) {
    setInterval(reloadMessages, 7000);
  }
});
```

```haml:hamlファイル
.message{data: {message: {id: message.id}}}
  .message__info
    .message__info__member
      = message.user.name
    .message__info__date
      = message.created_at.strftime("%Y年%m月%d日 %H時%M分")
  .message__text
    - if message.content.present?
      %p.message__text__content
        = message.content
    = image_tag message.image.url, class: 'lower-message__image' if message.image.present?
```