rails 4.2.5
ruby 2.1.3
railsアプリの作成
$ rails new websocket
gemの追加
gemのインストール
$ gem install websocket-rails
gemfileにwesocket-railsを追加
gem `websocket-rails`
これで$ bundle install
websocket-railsで使うものをinstall
$ rails g websocket_rails:install
create config/events.rb
create config/initializers/websocket_rails.rb
append app/assets/javascripts/application.js
development.rbに追加
これを追加しないと、ローカルで動かないっぽい。
Rails.application.configure do
config.middleware.delete Rack::Lock
end
作成されたevent.rbに情報を追加する
event.rbはroutes.rbのようなもので、後に定義するjsで呼ばれるリクエストに対して、railsのコントローラーをマッピングしている。
自分の場合は、クライアントでsend_messageというリクエストがあれば、Websocket_message_controller.rbのrecieve_messageメソッドでさばくよってことを書いている。
WebsocketRails::EventMap.describe do
# You can use this file to map incoming events to controller actions.
# One event can be mapped to any number of controller actions. The
# actions will be executed in the order they were subscribed.
#
# Uncomment and edit the next line to handle the client connected event:
# subscribe :client_connected, :to => Controller, :with_method => :method_name
#
# Here is an example of mapping namespaced events:
# namespace :product do
# subscribe :new, :to => ProductController, :with_method => :new_product
# end
# The above will handle an event triggered on the client like `product.new`.
subscribe :send_message, :to => WebsocketMessageController, :with_method => :recieve_message #追加したところ
end
event.rbで指定したcontrollerを手動で自分で作成する
rails g controller websocket_message
作成したコントローラーにevent.rbで指定したメソッドを追加
先ほど指定したrecieve_messageメソッドの作成
class WebsocketMessageController < WebsocketRails::BaseController
def recieve_message
message = message();
broadcast_message :show_message, message
end
end
message()
クライアントからのメッセージを取得する。
broadcast_message(event_name, message, options={})
引数event_nameのイベントとして、全クライアントへ引数dataを送信する。
[event_name] ・・・ 送信するイベント名を指定
[data] ・・・ 送信するデータを指定
[options] ・・・ namespaceなどのオプションがある場合に指定
message(),broadcast_messageメソッドはwebsocket-railsの中の決まり事。
他にもメソッドあります。
表示する用のcontrollerとviewの作成
$ rails g controller messages index
view側のコード
<% if user_signed_in? %>
<div id="message_box">
<p>broadcasting message</p>
<!-- 送信ボタンを押したらここにメッセージが表示される -->
</div>
<input type="text" id="message_input"> <!--フォームの作成 -->
<input type="button" id="send_message" value="send"> <!--フォーム送信ボタンの作成 -->
<script>
$(document).ready(function(e){
var dispatcher = new WebSocketRails('localhost:3000/websocket'); // WebSocketRailsオブジェクトを作成すると、websocket-railsのサーバーに接続することができる。URLはデプロイする時はちゃんとローカルホストではなくサイトのURLに変更する。
$(document).on("click", "#send_message", function(e){ //$(document) = HTML でclickイベントが発生したところが、send_message IDの要素を持っていたら、処理をする。という指定が.onを使うことによって指定できる。
message_text = $("#message_input").val(); //上のmessage_input IDのフォームに入力されたメッセージを.val()メソッドで取り出してmessage_textに入れている
dispatcher.trigger("send_message", message_text); //send_messageをリクエストして、websocket_message_controller.rbのrecieve_messageメソッドを呼び出している。 .trigger( "イベント名",パラメーター )
});
dispatcher.bind("show_message", function(message){ //.bindでwebsocket_message_controllerで定義したmessageを呼び出して、
$("#message_box").append("<p>" + message + "</p>"); //message_box IDの中に messageをappend(追加)する。
});
});
});
</script>
<% else %>
<% end %>
この.bindだけど、何か調べたら.onと同じだから.bind使うより.onを使ってくださいみたいなことが書いてあったから、.onにして確認して見たけど、動作しませんでした。わかる方コメントください。
これで、サイトを見ている人全員でチャットができるようになる。
と思いきや、まだはやい。
おそらく画面は表示されるが、メッセージを送信しても表示できないはず。
そしてデロッパーツールのNetworkで通信を確認すると、双方向通信が、30秒経つと勝手に切れてしまうことがわかる。
それは、websocket-rails gem を入れた時に勝手に入る、
faye-websocket
というgemのバージョンを変更してあげないと、うごかない。
ここで僕は訳がわからずハマりしました。
faye-websocketのバージョン変更
gem 'faye-websocket', '0.10.0'
$ bundle update
これで晴れてチャットができます。
自分はこれとdeviseを使って、ユーザー登録をするところまでできました。
最初deviseとwebsocket-railsを同時に入れようとしたらエラーが出てできなかったと思います。
なので、websocket-railsでチャットが動くのが確認できてから、deviseをいれたらちゃんとできました。
あと自分が実現したいことは、ユーザー間の1対1のラインみたいなやりとりと、チャットの保存。
でも文書が少なく、どうやって良いかわからず。
それは今後の課題で自分でちゃんと理解して試行錯誤してやっていくしかなさそう。