websocket-railsで特定ユーザにメッセージを送信する

準備

websocket-railsインストール を参照して環境構築

サーバ処理の作成

WebSocketイベント定義

config/events.rb

  subscribe :notify_user  , 'messages#notify_user'

WebScoketコントローラ作成

app/controller/messages_controller.rb

class MessagesController < WebsocketRails::BaseController

  def notify_user

    logger.debug("notify_user!");

    # 未ログイン時は何もしない
    if !current_user
      return
    end 

    uid        = message[:uid]
    from_uid   = current_user.id
    from_user  = User.find(from_uid)
    from_email = from_user[:email]

    result = false
    #if WebsocketRails.users[uid]                        # これだとWebsocketサーバが落ちる  ※1
    if WebsocketRails.users.users[uid]
      if WebsocketRails.users[uid].connected?
        WebsocketRails.users[uid].send_message('notification', { :msg => message[:msg], :from => from_email , :type => "user" })
        result = true
      end 
    end 

    # 結果通知
    if result
      logger.debug("notify OK!");
      trigger_success({ :msg => "send OK!"})
    else
      logger.debug("notify error!");
      trigger_failure({ :error => "error!"})
    end 

  end 

  .
  .
end

※1 ... find_remote_user から呼ばれている WebsocketRails.synchronize? , Synchronization.find_user(identifier) , remote_connection のどれかだと思うが詳しくは見ていない。
 ここでは UserManagerのインスタンス変数(@users)を直接見る事で回避したが、リアルタイム性を追求する場合は不都合があるかもしれない。

共通処理(js)の作成

app/assets/javascript/_common.js

jQuery(function($){

  var myapp = window.myapp = window.myapp || {};

  /**
   * websocket接続処理
   */
  myapp.wsConnected = false;
  myapp.wsConnect = function(){
    if (myapp.wsConnected) {
      return;
    }
    myapp.dispatcher = new WebSocketRails(location.hostname + ":3001/websocket");
    if (myapp.dispatcher) {
      myapp.wsConnected = true;
      console.log("ws connect!");
      myapp.dispatcher.bind('connection_closed', function() {
        console.log("ws close!");
        myapp.wsConnected = false;
        myapp.wsConnect();
      });
    } else {
      console.log("ws connect error!");
    }
  };

  /**
   * 全体通知のsubscribe
   */
  myapp.subscribed = {};
  myapp.subscribe_default = function(event_name){
    event_name = event_name || "notification";
    if (myapp.subscribed[event_name]){
      return;
    }
    myapp.dispatcher.bind(event_name, function(data) {
      console.log("websocket receive message");
      myapp.showNotifyDialog(data);
    });
    myapp.subscribed[event_name] = true;
  };

});

メッセージ送信用画面の作成

コントローラの作成

app/controller/chats_controller.rb

class ChatsController < ApplicationController

  #
  # 全ユーザへのメッセージ送信画面
  #
  def alls

  end 

  #
  # ユーザ一覧を表示する
  #
  def users

    @users = user_list
    @uid = params[:uid] || nil 
    @msg = params[:msg] || nil 

    if request.post?
      to_user
    end 

  end 

  private

    #
    # ユーザ一覧を取得する.
    #
    def user_list

      users = []

      online_users = []
      WebsocketRails.users.each do |conn|
        online_users << conn.user[:id]
      end

      all_users = User.all
      all_users.each do |u|
        rec = u.attributes.compact!
        rec["status"] = online_users.include?(rec["id"])
        users << rec
      end

      users
    end

ビューの作成

app/views/chats/users.html.erb

<h3>ユーザを指定してメッセージを送信する</h3>

<%= render :partial => "shared/messages" %>

<%= form_tag('/chats/users', :method => :post, :id => "sendto_user_form") do %>

<div>ユーザ</div>
<table class="tbl">
  <thead>
  <tr>
    <th> </th>
    <th>Email</th>
    <th>オンライン</th>
  </tr>
  </thead>
  <tbody>
<% @users.each_with_index do |u,i| %>
  <tr>
    <td><input type="radio" name="uid" value="<%= u["id"] %>" <%= @uid.to_s == u["id"].to_s ? "checked=checked" : "" %> /></td>
    <td><%= u["email"] %></td>
    <% if current_user[:id].to_s == u["id"].to_s %>
    <td>自分</td>
    <% else %>
    <td><%= u["status"] ? "◯" : "" %></td>
    <% end %>
  </tr>
<% end %>
  </tbody>
</table>

<br />

<div>メッセージ</div>
<div>
  <textarea name="msg" rows="5" cols="40"><%= @msg %></textarea>
</div>

<input id="btn_ws"     type="button" value="メッセージ送信" />

<% end %>

クライアント処理の作成

app/assets/javascript/chats/users.js

jQuery(function($){

  /** 
   * [websocket送信]
   */
  $(document).on("click", "#sendto_user_form #btn_ws", function(e){
    var data = { "uid" : $("form").find("[name=uid]:checked").val(),  "msg" : $("form").find("[name=msg]").val() };
    myapp.dispatcher.trigger("notify_user", data,
     function(data){
       console.log("送信しました。");
     },  
     function(data){
       alert("送信できませんでした。");
     }   
    );  
  }); 

  // ws接続
  myapp.wsConnect();

  // subscribe
  myapp.subscribe_default();
});

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-12-26 (月) 00:16:14 (1596d)