railsでチャット機能

rails 4.2.5
ruby 2.1.3

#railsアプリの作成

`$ rails new websocket`


# gemの追加

gemのインストール

`$ gem install websocket-rails`

gemfileにwesocket-railsを追加


```gemfile
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に追加
これを追加しないと、ローカルで動かないっぽい。

```config/environments/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メソッドでさばくよってことを書いている。

```config/event.rb
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メソッドの作成

```app/controller/websocket_message_controller.rb
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側のコード

```app/view/messages/index.html.erb
<% 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のバージョンを変更してあげないと、うごかない。
ここで僕は訳がわからずハマりしました。

https://github.com/websocket-rails/websocket-rails/issues/379

#faye-websocketのバージョン変更

```gemfile
gem 'faye-websocket', '0.10.0'
```

`$　bundle update`

これで晴れてチャットができます。

自分はこれとdeviseを使って、ユーザー登録をするところまでできました。
最初deviseとwebsocket-railsを同時に入れようとしたらエラーが出てできなかったと思います。
なので、websocket-railsでチャットが動くのが確認できてから、deviseをいれたらちゃんとできました。



あと自分が実現したいことは、ユーザー間の１対１のラインみたいなやりとりと、チャットの保存。
でも文書が少なく、どうやって良いかわからず。
それは今後の課題で自分でちゃんと理解して試行錯誤してやっていくしかなさそう。