亀の速度で走る

"Computer Programming is the closest thing we have to a superpower."

ジャックドーシーにしびれる

Square

Squareについて調べてて、ジャックドーシーの言葉がかっこよくて痺れたので。

You. You’re the future. You have the ideas. That’s your task. Sometimes you win. Sometimes you lose. But it’s up to you to make what you want to see the world.

君。君が未来だ。君がアイディアを持っている。それがあなたの勤めだ。もしかしたら勝てるかも。もしかしたら負けるかも。でも、君が見たい世界を創るか創らないかは君次第。


ちなみに、このブログのサブタイトルは、DropBoxのドゥリュー・ヒューストンの言葉です。

Computer Programming is the closest thing we have to a superpower

コンピュータープログラミングはスーパーパワーに一番近い力だ。


あー、かっこいいな

Go lang で Hello World

Go Lang

先日友達がごうこんに行ってきたらしいので詳しく聞いたら、Go Conferenceだった。
そんな形で知ったGo Langでこちらの記事を参考にHello Worldしてみた。

バージョン

CentOS Linux release 7.0.1406 (Core)

インストール

cd /usr/local/src
wget https://storage.googleapis.com/golang/go1.2.2.linux-amd64.tar.gz
tar -C /usr/local/ -xzf go1.2.2.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

Hello World

package main

import "fmt"

func main() {
  fmt.Printf("hello, world\n")
}

実行

go run hello.go

表示

hello, world


わーいわーい!

Websocket Railsを使って特定のユーザーにメッセージを送る

特定のユーザにメッセージを送る

前回のブログ記事でWebsocket Railsを用いて接続が確立したユーザ全員にメッセージを送る実装方法について書きました。今回はFacebookのプライベートメッセージのように特定のユーザにメッセージを送りたい時にどうしたら良いのかを書いていきたいと思います。(この記事では省略していますが、参考サイトに載せているGithubのページのInstallation Guildeに従ってWebsocket Railsのインストールをして下さい。または前回の記事を見て下さい。)

参考サイト

前回同様Websocket Railsを使っていきます。今回も本家のサイトこちらのサイトを参考にしました。

特定のユーザの指定方法

さて、どうやって実装したらいいのかな。と少し調べていたら、本家のサイトにこのような事が書いてありました。ふむふむ。UserManagerとやらを使うらしい。

You can send an event to a specific client using the UserManager which can be accessed via WebsocketRails.users.

myUser.idとは何かな?WebsocketRails.usersとは?

WebsocketRails.users[myUser.id].send_message('new_notification', {:message => 'you\'ve got an upvote '})


それは二個目の参考サイトにこのように書いてありました。

If there is a `current_user` method defined in ApplicationController and a user is signed in to your application when the connection is opened, WebsocketRails will call the method defined in `config.user_identifier` on the `current_user` object and use that value as the key.If no `current_user` method is defined or the user is not signed in when the WebsocketRails connection is opened, the connection will not be stored in the UserManager.

なるほど。application controllerにcurrent_userメソッドを定義しておけばWebsocketの接続が確立されたと同時にUserManagerにユーザの情報を格納してくれるらしい。便利ですなー。

実装方法

もう既に出来上がっているサイトで、ごちゃごちゃしていてどこから説明していいのか分からないので、必要最低限の部分をメモ程度に書いていこうと思います。既にユーザなどは存在する体でお願いします。ちなみにUIはこのような形です。画像があった方が少しはイメージし易いかもしれません!

f:id:takuyanz:20150130210124p:plain


まず参考サイトに書いてあったようにapplication_controllerに current_userを定義します。これがないと始まらない。

def current_user
 return unless session[:user_id]
 @current_user ||= User.find(session[:user_id])
end


前回のブログ同様JS側でWebsocketの接続を確立させるコード、Websocketを通してサーバー側から送られてきたメッセージを表示するコードを書きます。実際に書いたコードをかなり簡略化させています。

$(document).ready(function(e){
  var ws_rails = new WebSocketRails("localhost:3000/websocket");
 
  ws_rails.bind("websocket_message", function(message){
  //json形式で送られてくるのでパースします
   var data = JSON.parse(message);
 
  //データをゴニョゴニョしてHtmlを生成して、appendします
   $("#message_box").append(ゴニョゴニョされたやつ);
  });
});


これでほとんど完成です。後はコントローラー側でメッセージがCreateされた時に以下のコード書きます。

message = "message"
WebsocketRails.users[送りたいユーザーのID].send_message('websocket_message', message)


下記がメッセージがcreateされた時の実際のコードになります。少し汚いかもしれません。リーダブルコード読み直すので許して下さい。

 def create
    #これらの情報はajaxで送られてきています
    msg_to_id = params.require(:message_to_id)
    message_text = params.require(:message_text)


    # 新しくmessageを作ります。message_from_idは今のユーザIdを格納
    message = Message.new(message_to_id: msg_to_id, message_from_id: current_user.id, text: message_text)

    if message.save
   #JS側でHtmlを生成する為の情報を変数に格納します
   #message:メッセージの内容 image_url:送り主のプロフィール画像 nickname:送り主の名前 message_id:メッセージのID created_at: 時間
      message_data = {message: message_text, image_url: current_user.image_url, nickname: current_user.nickname, message_id: message.id, created_at: message.created_at.strftime("%X %d/%m")}.to_json

      # Websocketを用いて今メッセージを送ったユーザと送られたユーザーにメッセージを送ります。
      # 同時に二人は出来ないっぽい
      WebsocketRails.users[msg_to_id].send_message(:websocket_message, message_data)
      WebsocketRails.users[current_user.id].send_message(:websocket_message, message_data)
     
      render nothing: true
     else
      render status: 500
     end
  end


これで動くと思います。
因みにbinding.pryでWebsocketRails.users(UserManager)の中身を見てみるとこんな感じです。ちゃんとユーザのデータが格納されています。

[1] pry(#<MessagesController>)> WebsocketRails.users
=> #<WebsocketRails::UserManager:0x000000091e7180
 @users=
  {"2"=>
    #<WebsocketRails::UserManager::LocalConnection:0x000000091e70e0
     @connections=
      [#<Connection::23c23305067da6ce6f36>,
       #<Connection::49eb23fad9a1acfd2154>,
       #<Connection::94af81b53170778b8d91>,
       #<Connection::df220cd8d761665985bc>,
       #<Connection::b26cc68e6842a8cff094>,
       #<Connection::dd73e630844a776c05a9>]>,
   "1"=>
    #<WebsocketRails::UserManager::LocalConnection:0x00000007d3d0e0[f:id:takuyanz:20150130230126p:plain]
     @connections=[#<Connection::88238ad7c31d08b3dc8d>, #<Connection::611d13d332b53cf85051>, #<Connection::946088f8474222d7640d>]>}>


Websocketの接続を確立させる時に以下のコードよりは、

var ws_rails = new WebSocketRails("localhost:3000/websocket");

実際にサイトをWeb上に上げる事を考えて以下のように書くと、ベターかも。

var ws_rails = new WebSocketRails(location.host + "/websocket");


この方法で以下のような通知機能や、新しいコンテンツがある場合のプラス+1なども実装する事が出来ました。

f:id:takuyanz:20150130230126p:plain


f:id:takuyanz:20150130230121p:plain


説明が少し分かりにくかったかな?技術系の記事を書いた事がないので、これから書きながら慣れていきたいと思います。

Websocketってすごいな。とにかく感動しまくりでした。Webアプリケーションを作りたいとプログラミングを始めて5か月が経とうとしています。サイトが裏でどのような動きをしているのかが分かってきて、わくわくしております。わくわくわくわく。

:)

Websocket Railsを使ってみたお話

何について

先日Railsを使って初めて作ったサイト(こちら)で Websocketを使ってみたので忘れないようにメモっておこうと思う。
 

Websocket

まず第一にWebsocketって何なのか?美味しいのか、美味しくないのか?

Websocketとはクライアントとサーバーで双方向通信ができる技術らしいです。つまり、クライエント側からサーバにリクエストする事もできるし、サーバ側からも何らかのアクションをクライエント側に起こす事ができる(サーバプッシュ)。こんな感じで大雑把に理解している。(参考サイト

 

WebsocketRails

とりあえず実際に使ってみる事に。今回は主に公式Githubページとこちらの記事がとても分かりやすかったので参考にさせて頂きました。
まずブロードキャスティングから。ブロードキャスティングとはWebsocketの接続が確立されているユーザー全員にサーバープッシュを行います。

では、初めからやってみましょう。とりあえずお決まりのコマンドを走らせます。

rails new demo
bundle install --path vendor/bundle


Gemfileに以下を足す。もう一度bundle install。

gem "websocket-rails"


次にこちらのコマンド。

rails g websocket_rails:install
      create  config/events.rb
      create  config/initializers/websocket_rails.rb
      append  app/assets/javascripts/application.js


Development環境でwebsocketを動かすには以下のコードをconfig/environments/development.rbに足す必要があるらしい。ふむふむ

config.middleware.delete Rack::Lock


早速config/evetns.rbを開いて下記を付け足します。下記は後に書いていくJS側で呼ばれるsend_messageに対して、WebsocketMessageControllerのrecieve_messageのメソッドが呼ばれるという意味。

subscribe :send_message, :to => WebsocketMessageController, :with_method => :recieve_message


次に上のファイルで指定したコントローラーを手動で作成します(app/controller/websocket_message_controller.rb)。こちらのファイルには下記を書いていきます。これでメッセージをブロードキャスティングする準備はほぼ整いました。

class WebsocketMessageController < WebsocketRails::BaseController
  def recieve_message
  message = message();
  broadcast_message :show_message, message
  end
end


次に以下のコマンドを使い、クライエントサイドを作っていきましょう。Controllerを作成するのは、Indexページを表示する為。

bundle exec rails g controller messages index --no-helper --no-assets


作成したHtmlファイルに以下を書き足します。(app/view/messages/index.html.erb)

  <div id="message_box">
    <p>broadcasting message</p>
    <!-- message will be shown here -->
  </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');

  $(document).on("click", "#send_message", function(e){
    message_text = $("#message_input").val();
    dispatcher.trigger("send_message", message_text);
  });

  dispatcher.bind("show_message", function(message){
    $("#message_box").append("<p>" + message + "</p>");
  });
});
</script>


これでブロードキャスティングのメッセージ機能は完成です。rails サーバーを起動させて、http://localhost:3000/messages/index にアクセスしてみましょう。

rails s

これで動くはずです。
ここまでは結構色々な方々がやっていて比較的情報が手に入れやすくスムーズに出来ました。でも今回サイトを作るにあたって実装したかった機能は特定のユーザにのみメッセージを送る事。次回の記事で少し触れてみようと思います。

:)