初心者プログラマのひとり勉強部屋

若葉マークのプログラマー☺️

【ruby on rails】非同期通信(メッセージ投稿の実装)

こんにちは!

 

今週はずっと非同期通信の実装をやっていたため非同期通信の実装の備忘録をメモ。

(※初心者blogで初心者コードなのはご容赦ください。) 

 

作っているもの

メッセージと画像が投稿できるチャットアプリ

 

やりたいこと

・画面をリロードせずにメッセージや画像を投稿

(←非同期通信)

・画面を一番下(最新のメッセージ投稿のところ)までスクロール

 

 

使った材料

rails (5.0.7.2)

jquery-rails

jbuilder (2.9.1)

haml

(非同期通信せずともメッセージは投稿できる状態です!)

 

そもそも非同期通信とは、、

画面をリロードせずに(画面遷移せずに)ページの内容を変更させること

(イイネ!機能も実装できるようになりたい!)

 

まず流れ!

jQueryajax通信用のファイルつくる

②controllerにrespond_to記載(jsonの処理できるようにする)

③jsファイルにjQuery記載

・フォームに入力して「送信」ボタン押すとイベント発火

ajax通信でcontrollerにviewから取ってきた値をparamsとして送る

jbuilderファイル記載(controllerの変数とviewの変数との翻訳ファイルみたいなもの)

⑤controllerでDB保存の処理が行われる(実装済み)→JSONへ飛ぶ

⑥(このままではjsで受け取れないため)jbuilderファイルを作って受け取り方法を定義

⑦jsファイルに値が帰ってくるためjQuery記載

・jsで.done(帰ってきた値)で受け取る

・帰ってきた値を入れてHTMLを作り、appendすることで表示させる

 

 

詰まった点

ajaxで送るurlの設定どうなってるの?

→自分で書いたHTMLのaction属性指定する

・image取ってこれない!

→このアプリはCarrierWaveを利用していてimage.urlを取ってきている(そういえばGemインストールした、、)

jbuilderで取ってくる値を@message.imageから@message.image.urlに変更

(ちなみに@message.image.urlは@messageにはない。どこにあるのかというとCarrierWaveの中のファイルに定義されているメソッド内)詳細は後ほど追記

 

実際のコード

記述(message.js)

 
$(document).on('turbolinks:load'function() {

var html_source=$(".aaa");

  function addHtml(message){
    var html=`
        【追加したいHTML文を書く】
        `
    html_source.append(html) //.aaaの最後にHTML文append  
  }

  $('#bbb').on('submit',function(e){
    e.preventDefault();  //送信ボタン押した状態で処理とめる
    var dt=new FormData($(this).get(0)); //get(0)でthisの一つ目の要素を取得
    var url = $(this).attr('action')
 
  //ajax通信でcontrollerに送る内容
    $.ajax({
      url:url,
      type:"POST",
      data:dt,
      dataType: 'json',
      processData: false,
      contentType: false,
    })
//controllerから帰ってきた値を受け取る(引数はなんでもいい)
    .done(function(data){
      addHtml(data); //上に定義したaddHtmlに飛ぶ
   //一番下まで移動(scrollTopで上まで移動、scrollHeightでaaa一個分ずつ下に移動
      $('.aaa').animate({ scrollTop: $('.aaa')[0].scrollHeight });
        $('#bbb')[0].reset(); //フォームのテキストボックスをからにする
      $('.send').attr('disabled'false); /preventdefoultで止めていた処理再開
    })
    .fail(function(){
      alert('error');
      $('.send').attr('disabled'false);
    })
    })

  

記述(message.controller)必要ないところは省略

  def create
    @message = @group.messages.create(message_params)
    respond_to do |format|
      format.html{
        if @message.save
          redirect_to group_messages_path(@group), notice: 'メッセージが送信されました'
        else
          @messages = @group.messages.includes(:user)
          flash.now[:alert= 'メッセージを入力してください。'
          render :index
        end
      }
      format.json
end
 
  def message_params
    params.require(:message).permit(:content:image:created_at).merge(user_id: current_user.id)
  end

 

今見直すと余計なコードがちらほら、、

最初に流れを把握していなかったため、冗長なコードから記載を減らしていきました。

 

結論

流れさえ把握していればそんなに時間かけずにかけた気がする、、!

 

※あくまでも初心者コード、初心者目線です。間違っていること・余計わかりづらいことを書いておりましたらご指摘くださいませ。