rails 、postgresql、zeroMQ、websocketを使って通信するサンプル環境を作成中

create rails project

cd 任意のディレクトリ
rails new test_rails_postgres -d postgresql
cd test_rails_postgres
bundle install --path vendor/bundle
bundle exec rake db:create db:migrate

テスト起動確認

cd test_rails_postgres
rails server
http://[サーバアドレス]:3000へアクセス

git 管理開始

cd test_rails_postgres
git init
vim .gitignore
以下を追加
    doc/
    *.swp
    *~
    .project
    .DS_Store
    .idea
    .secret
git add .
git commit -m "initial commit."

テスト設定

bundle exec rails generate scaffold book title:string author:string outline:text
bundle exec rake db:migrate
bundle exec rails server

db確認

-- database list
\l
-- user list
select * from pg_user;
-- table list
\d

routes の確認

http://localhost:3000/rails/info/routes

rails へwebsocket実装

websocket-rails install

cd test_rails_postgres
vim Gemfile
# 以下を追加  
    gem 'websocket-rails'
bundle install
rails g websocket_rails:install
# コントローラ作成
vim app/controllers/websocket_chat_controller.rb
    # WebsocketRails::BaseControllerを継承
    class WebsocketChatController < WebsocketRails::BaseController
      def message_recieve
        # クライアントからのメッセージを取得
        recieve_message = message()
        # websocket_chatイベントで接続しているクライアントにブロードキャスト
        broadcast_message(:websocket_chat, recieve_message)
      end
    end
vim config/events.rb
    WebsocketRails::EventMap.describe do
          # websocket_chatイベントのマッピング
        subscribe :websocket_chat, to: WebsocketChatController,
        with_method: :message_recieve
    end

# クライアント
rails g controller chat index
vim app/views/chat/index.html.erb
以下追加
    <!-- チャット表示部分 -->
    <ul id="chat_area">
    </ul>
    <!-- コメントフォーム -->
    <input id="comment" type="text">
    <input id="send" type="button" value="send">
    <script>
      var ws_rails = new WebSocketRails("[url]:3000/websocket");
      // メッセージ受信時の処理
      ws_rails.bind("websocket_chat", function(message){
        var message_li = document.createElement("li");
        message_li.textContent = message;
        
        document.getElementById("chat_area").appendChild(message_li);
      })
      // メッセージ送信時の処理
      document.getElementById("send").onclick =  function(){
        var comment = document.getElementById("comment").value;
        ws_rails.trigger("websocket_chat", comment);
      }
    </script>
vim config/environments/development.rb
    # 以下を追加
    config.middleware.delete Rack::Lock

test websocket client作成

gem install

gem install websocket-client-simple

client program(動かない)

vim websocket_client.rb
    require 'rubygems'
    require 'websocket-client-simple'
    
    ws = WebSocket::Client::Simple.connect '[url]:3000/websocket'
    
    ws.on :message do |msg|
      puts msg.data
    end
    
    ws.on :open do
      ws.send 'hello!!!'
    end
    
    ws.on :close do |e|
      p e
      exit 1
    end
    
    loop do
      ws.send STDIN.gets.strip
    end

execjs install(不要)

gem install execjs

zeromq install

cd 任意のディレクトリ
git clone https://github.com/zeromq/zeromq4-x.git
cd zeromq4-x
# git checkout origin/v4.0.1
sudo aptitude install libtool autoconf uuid-dev
./autogen.sh
#./configure --prefix=/usr/local/zmq
./configure
make
sudo make install

ZeroMQ導入

vim Gemfile
--------------------
# Use zeroMq
gem 'rbzmq'
#gem 'ffi-rzmq'
#gem 'zqm'

ffi-rzmqのバージョンが合っている2.0.1が要る?

rails コントローラにZMQスレッドを立ち上げる

vim websocket_chat_controller.rb
---------------------------------------------------
require 'rbzmq'
# WebsocketRails::BaseControllerを継承
class WebsocketChatController < WebsocketRails::BaseController
  context = ZMQ::Context.new
  publisher = context.socket ZMQ::PUB
  publisher.bind "tcp://*:5563"
  begin
    t = Thread.new do
      Thread.pass    # メインスレッドが確実にjoinするように
      puts "[rails] Tread loop start."
      loop do
        publisher.send_string 'A', ZMQ::SNDMORE
        publisher.send_string "We don't want to see this."

        publisher.send_string 'B', ZMQ::SNDMORE
        publisher.send_string "We would like to see this."

        sleep 1
      end
      publisher.close
      raise "unhandled exception"
    end
    t.join
  rescue
    p $!  # => "unhandled exception"
  end

  puts "[rails] WebsocketChatController is started!!!!!"
  def message_recieve
    # クライアントからのメッセージを取得
    recieve_message = message()
    puts "[rails] server message receive and broadcast => #{recieve_message}"
    # websocket_chatイベントで接続しているクライアントにブロードキャスト
    broadcast_message(:websocket_chat, recieve_message)
  end
end

rails server立ち上げ

bundle exec rails server

em-websocket in rails

  • vim websocket_chat_controller.rb require “em-websocket” # 省略 puts “rails emwebsocket server start” # 配列ではなくEventMachineオブジェクトを生成 connections = EM::Channel.new EM::WebSocket.start(host: “172.19.1.94”, port: 3001) do |ws_conn| ws_conn.onopen do puts “connected” # EventMachine#subscribeを用い、コネクションオブジェクトと処理を登録 connections.subscribe{|message| ws_conn.send(message) } end ws_conn.onmessage do |message| # onopen内で登録した処理を呼び出し puts “received:” + message connections.push(message) end end