Ruby on Railsとrubymotionでリアルタイムweb構築

##リアルタイムweb？
リアルタイムにwebの情報をサーバからのpush通知で更新する。
有名どころでいうとFB、Chatwork、Twitterとか。

技術的には方法が大きく3つある。

####・ポーリング(Polling)
一定の時間に一度、Ajaxでサーバに接続させ
新しい情報がないかどうか調べる。擬似的なプッシュ型。

####・コメット(Comet)
クライアントから送られてきたレスポンスをすぐに返さずに処理中の形を取ってコネクションを張ったままにする。
新着の情報があったタイミングでレスポンスを返す。

####・Websocket
HTML5より作られた新しい通信規格。独自のプロトコルを持つ。
先程の2通りのデメリットを補いより効率よく双方向通信が可能。

今回は技術的な流れも含め、Websocketを用いる。

##railsでどうやって構築する？

railsを用いる事をmustとするなら調べた中だと多く3つ。

####・Live Streming
rails4より導入された Live Streming機能。
HTTPコネクションで行うようなので、Polling/Comet系
Rails側のバージョンアップで今後は進化するのか？

####・Node.js + Socket.io の併用
DB周りのみrailsに担当させて、Redis + Node.js + Socket.ioでクライアントとはやり取りをする。
だったらrailsってこだわる必要あるのか？とも思ったり。

####・websocket-rails
railsでwebsocketを使用する方法では、一番主流？
https://github.com/websocket-rails/websocket-rails

EventMachine使ってるし、イベント駆動型なので
パフォーマンス的にも大丈夫かなー・・・

今回は一旦 websocket-railsで。実行。


##rubymotionでどうやって構築する？

squareが作ってるSocketRocketというライブラリを使う。

##インストール

まずはwebsocket-railsから。

```Gemfile
gem "websocket-rails"
```

```
$ bundle
$ rails g websocket_rails:install
```

開発環境ではRack::Lockを無効にしないとエラーになるので以下のように設定。

```config/environments/development.rb
config.middleware.delete Rack::Lock
```

次にSocketRocket。

```Rakefile
app.pods do
   pod 'SocketRocket'
end

```
これで完了。

##実装
まずはwebsocket_rails側から。(※基本は以下見ればわかります)
https://github.com/websocket-rails/websocket-rails

websocket_railsが用意してくれる "/websocket"につなぐ。

```test.js
var dispatcher = new WebSocketRails("ws://yourhost/websocket");

dispatcher.on_open = function() {
    return console.log("Connection has been established: ");
  };

dispatcher.bind('hoge', function(){
    alert('fuga');
  });

$('#hoge').click(function(){
  dispatcher.trigger('hoge.send', 'hogefuga');
});

```

```config/events.rb
WebsocketRails::EventMap.describe do
  namespace :hoge do
    subscribe :send, :to => HogeController, :with_method => :send
  end
end

```

```app/controllers/hoge_controller.rb
class HogeController < WebsocketRails::BaseController
    
  def send
    broadcast_message :hoge, message
  end
end

```

ダラダラ書きましたが、上記のような形でクライアントとサーバのやり取りが可能です。

クライアント→サーバでのやりとりは、triggerを使ってjs側で設定し、それをevent.rbに明記してcontroller側に送る。
といった至って簡単な構造。

ちなみにbroadcast_messageとすると全てのクライアントに対して送信してしまうので、分けたい場合はchannelというものを使うと実装可能。
またサーバ→クライアントの通信だけなのであれば、

```
WebsocketRails[:'channel名'].trigger 'hoge', 'fuga'
```
とすればchannel名をsubscribeしているものにだけpush通知ができたり。何とも簡単。

次にrubymotion。

```
url = NSURL.URLWithString("ws://49.212.87.13:3006/websocket")
@socket = SRWebSocket.alloc.initWithURLRequest(NSURLRequest.requestWithURL(url))                                                                                                           
@socket.delegate = self
@socket.open

def webSocket(webSocket, didReceiveMessage:message)
  p message
end
```

っていう感じに書いておけば、rakeしたときに通信してくれる。

rails側でlog/websocket_rails.logのファイルを確認してみると確かにrubymotionからもwebsocketで繋がれている。

その他はそれぞれのgithubでも見ながら追加していってください。

参考文献

- websocket-railsで簡単なPush通知を実装する
http://qiita.com/naoty_k/items/3a2b5d8cfc1619e6145b

- RubyMotionからWebSocketを使う
http://qiita.com/bellx2/items/84bbcdcaf1b37b5483f3

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

- SocketRocket
https://github.com/square/SocketRocket