logo logo

March 09, 2019 04:06

gonのajax通信時リロード

実現したかったこと

railsにおいてサーバーサイドのデータをJava Scriptに受け渡す際にはgonというgemを使った実装をされることが多いのではないでしょうか。

今回はajax通信の際にgonの中身を更新し、同時にJSサイドに受け渡すという機能を実装したかったのですが、
gonオブジェクトはナイーブな使用法だとheader読み込みの際に一度だけ読み込まれるため、少し工夫が必要でした。
公式によるとgon.watchという機能が実装されていて、定期的にサーバーデータを読みこむこともできるようですが、
サーバー通信が頻繁になってしまうのと、どうも想定のと異なった動きだったので、

RailsでjavaScriptにデータを渡すgem gonをajax時に再読み込みする

こちらを参考に実装したところ解決できました。以下は備忘録としてメモ。Thanx!

実装

公式にもある通常のgonのローディングはapp/views/layouts/application.html.erbのhead内に挿入する以下のワンラインによって行われる。

<%= include_gon %>

しかしこれだとajaxで呼び出したコントローラで、サーバー側でgonの更新を行っても、クライアント側では反映されない状態になってしまう。そこで、ajax呼び出ししたコントローラでこのワンラインを実行するためのパーシャルを呼び出す。

まずはコントローラで

def called_by_ajax
  # gonオブジェクトのサーバー側での更新処理
  gon.hoge = hoge
  # パーシャルの呼び出し
  render partial: "share/gon_partial"
end

呼び出されたパーシャル(この場合ならshare/gon_partial)に以下のワンラインを埋め込んでおく。

<%= include_gon %>

最後にajax通信の完了をトリガーに所望のJava Scriptを発動させる。

$(".ajax_form").on("ajax:complete", function(e) {
  var response = e.detail[0].response;
  $('head').append(response);
  // 何らかの処理
});

リアルタイム或いは定期更新したい際

この場合は公式のgon.watchを使うのが良さそう。チャットアプリや何らかのリアルタイム通知を実装したい場合などに使えそう。
チャットタイムラインの更新をイメージして実装フローだけメモる。(動作確認未済)

Gonの使い方 まとめ - 猫Rails

  • コントローラでの処理
def index
  @messages = Chatboard.messages
  gon.watch.messages = @messages
end
  • ビュー:中身をajax通信で更新していく
<div id='chat_board'>
</div>
  • Java Scriptでの処理
function chatBoardUpdate() {
  // chat_boardタグをターゲットにした更新時のビュー反映処理
}

// こちらでgonオブジェクトをインターバル引数で指定した頻度(単位: ms)で監視。定義済みのコールバック関数と紐づけておく
gon.watch('messages', interval: 1000, chatBoardUpdate)