Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

chat-space自動更新機能の実装

More than 1 year has passed since last update.

流れ

⑴表示されているメッセージのHTMLにid情報を追加
⑵メッセージを更新するためのアクションを実装
⑶追加したアクションを動かすためのルーティングを実装
⑷追加したアクションをリクエストするよう実装
⑸取得した最新のメッセージをブラウザのメッセージ一覧に追加
⑹数秒ごとにリクエストするよう実装
⑺メッセージ分だけスクロールするよう実装
⑻メッセージ一覧のページでのみJSが動くよう実装

⑴表示されているメッセージのHTMLにid情報を追加

_message.html.haml

//メッセージ全体にidを付与。   ※#{message.id}はjbuilderファイルで定義している
.message{"data-message-id": "#{message.id}"}

⑵メッセージを更新するためのアクションを実装

コントローラーのapiディレクトリの中に、messages_controller.rbを作成

messages.controller.rb
#APIの中にありますよーって意味
class Api::MessagesController < ApplicationController

  def index

#今いるグループの情報をparamsによって取得し変数@groupに代入
    @group = Group.find(params[:group_id]) 

#グループ内のメッセージでlast_idよりも大きいidのメッセージがないかを探してきてそれらを@messageに代入
    @messages = @group.messages.includes(:user).where('id > ?', params[:last_id])
  end
end

⑶追加したアクションを動かすためのルーティングを実装

ルーティングの追加

routes.rb
Rails.application.routes.draw do
  devise_for :users
  root 'groups#index'
  resources :users, only: [:index, :edit, :update]
  resources :groups, only: [:new, :create, :edit, :update] do
    resources :messages, only: [:index, :create]
#ここからが追加
    namespace :api do
      resources :messages, only: :index, defaults: { format: 'json' }
    end
  end
end

jbuilderファイルも作成

index.json.jbuilder
json.array! @messages do |message|
  json.content message.content
  json.image message.image
  json.created_at message.created_at
  json.user_name message.user.name
  json.id message.id
end

⑷追加したアクションをリクエストするよう実装

message.js
//自動更新用の関数定義
let reloadMessages = function () {

//ブラウザに表示されている最後のメッセージからidを取得して、変数に代入
      let last_message_id = $('.message:last').data("message-id");

//ajaxの処理   
      $.ajax({

//今回はapiのmessagesコントローラーに飛ばす
        url: "api/messages",
//HTTP_メソッド
        type: 'get',
//データはjson型で
        dataType: 'json',

//キーを自分で決め(今回はlast_id)そこに先ほど定義したlast_message_idを代入。これはコントローラーのparamsで取得される。
        data: {last_id: last_message_id} 
      })

//doneの処理(仮)
    .done(function(messages) {
    console.log('success');
  })

//failの処理(仮)
    .fail(function() {
      console.log('error');
  });
};

⑸取得した最新のメッセージをブラウザのメッセージ一覧に追加

doneの中身の編集

message.js
.done(function (messages) { 

//追加するhtmlの入れ物をつくる
      let insertHTML = '';

//取得したメッセージたちをEach文で分解
      messages.forEach(function (message) {

//htmlを作り出して、それを変数に代入(作り出す処理は非同期の時に作った)
        insertHTML = buildHTML(message); 

//変数に代入されたhtmlをmessagesクラスにぶち込む
        $('.messages').append(insertHTML);
      })
    })

buildHTMLを一部編集

message.js
function buildHTML(message){
    let image = ( message.image ) ? `<img class= "lower-message__image" src=${message.image} >` : "";

//messageクラスにdata-message-idを付与
    let html = `<div class="message", data-message-id="${message.id}">


                    <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> `
  $('.messages').append(html);
  }

⑹数秒ごとにリクエストするよう実装

message.js
//これにより5000ミリ秒ごとにreloadMessagesが呼び出される※処理の外に記述
setInterval(reloadMessages, 5000);

⑺メッセージ分だけスクロールするよう実装

message.js
//doneの処理内に記述。非同期の方でも定義しているので、関数にしてまとめた方がなお良い
$('.messages').animate({scrollTop: $('.messages')[0].scrollHeight}, 'fast');

⑻メッセージ一覧のページでのみJSが動くよう実装

if文で関数を挟む

message.js
//今いるページのリンクが/groups/グループID/messagesのパスとマッチすれば実行
if (window.location.href.match(/\/groups\/\d+\/messages/)){

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away