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 のどれかだと思うが詳しくは見ていない。 共通処理(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(); }); |