websocket-railsを使ってRailsでリアルタイムチャットを実装する方法

こんにちは、インターンの@ij_spitzです。

以前@h3_potetoさんがwebsocket-railsで作ったチャットをAWSで公開する方法を
書いてくれたので、僕はアプリケーション側の実装方法を書きたいと思います!

作成の際は以下を参考にしました。
https://github.com/websocket-rails/websocket-rails

nginx + unicorn + redis という構成で作成したので、nginxやunicornの設定で少し躓いてしまいましたが、それを抜きにすればかなり簡単にチャットが実装できます!

目次

1. 設定/前準備
2. 設定ファイルを編集
3. JSの実装
4. コントローラーの実装

1. 設定/前準備

# Gemfileに追加
gem websocket-rails

# コマンドで設定ファイルを自動生成
$ rails g websocket_rails:install

# 開発の際はdevelopment.rbに以下を追加
config.middleware.delete Rack::Lock

2. 設定ファイルを編集


先ほどのコマンドで作成されたファイルを編集して、JSで取得したデータをコントローラーのメソッドに送るというように設定します。

  # config/event.rb 
  subscribe :client_connected, to: SocketController, with_method: :connect_user
  subscribe :new_message, to: SocketController, with_method: :new_message

3. JSの実装


JavaScriptでボタンがクリックされた際に@dispatcherを通してコントローラーにメッセージを送ります。
そしてコントローラーからプッシュ通知が送られてきたら、それをチャットページに追加します。

#= require websocket_rails/main

class @ChatClass
  constructor: (url, useWebsocket) ->
    @dispatcher = new WebsocketRails(url, useWebsocket)
    @events() # イベントを監視

  events: () =>
    # ボタンが押されたらメッセージを送信
    $('#button').on 'click', @submitMessage
    # サーバーからnew_messageを受け取った場合、receiveMessageを実行
    @dispatcher.bind 'new_message', @receiveMessage

  submitMessage: (event) =>
    # メッセージを取得し、サーバ側にnew_messageのイベントを送信
    msg_body = $('#text').val()
    @dispatcher.trigger 'new_message', { body: msg_body }

  receiveMessage: (message) =>
    # 受け取ったメッセージを追加
    $('.message').append "<p class='left'>#{message.body}</p>"

$ ->
  window.chatClass = new ChatClass($('#url').val(), true)

4. コントローラーの実装


events.rbで設定した通り、JavaScriptの@dispatcherから投げられたnew_messageというメソッドがSocketControllerのnew_messageというアクションに繋がります。
これを一旦DBに保存し、全ユーザーにプッシュ通知を送るため、再びJSに返します。

class SocketController < WebsocketRails::BaseController

  # Websocketサーバー起動時に実行されるメソッド
  def initialize_session
  end

  # ユーザー接続時に実行されるメソッド
  def connect_user
  end

  def new_message
    @message = Message.new(
      :message => message[:body]
    )
    status = @message.save ? 'success' : 'error'

    # コネクションのあるユーザー全てにメッセージを送る
    broadcast_message :new_message, message
  end

end

終わりに


以上でWEBrickなどで動かす場合は、チャットが完成です!
非常に簡単に実装ができるのがお分かりいただけたと思います。

ただ、今回、langmatch.comでは2人だけでチャットをしたい、unicorn + nginxで動かしたい、ということだったので、以下を参考にさらにいろいろ書き加えています。

余力のある人は参考に頑張ってみてください。
http://altarf.net/computer/rails/2502

以上、インターンの@ij_spitzでしたー!