LoginSignup
2
2

More than 5 years have passed since last update.

knockoutjsでwebsocket-railsをつかった手順まとめ

Last updated at Posted at 2014-11-07

概要

knockoutjsでwebsocket-railsをつかったので、導入した手順と、つまづいた点を紹介します。

つくったのは、ユーザーに紐づくタスクリストの「追加・編集・削除・完了」みたいなのが全クライアントに反映されるやつです。

データ的には、以下の様な感じです。ユーザーは何人かいます。

user: [{
    id: 1,
    name: aaaa,
    todo: [
        {id: 1, name: aaaaaaa, del: 1},
        {id: 2, name: eeee, del: 1},
        {id: 3, name: ccccc, del: 0},
        {id: 4, name: hhhhh, del: 0},
        {id: 5, name: kkkkk, del: 0},
    ]
},
{
    id: 2,
    name: aaaa,
    todo: [
        {id: 6, name: jjj, del: 1},
        {id: 7, name: ee, del: 1},
        {id: 8, name: gggg, del: 0},
    ]
},
{
    id: 3,
    name: aaaa,
    todo: [
        {id: 9, name: aaaaaaa, del: 1},
        {id: 10, name: eeee, del: 1},
        {id: 11, name: ccccc, del: 0},
        {id: 12, name: hhhhh, del: 0},
    ]
}]

websocket-railsを導入する

以下の記事を参考にしました。基本的には、手順通りやれば問題ないはずです。

簡単にまとめると、以下の5手順で完了します。

  1. websocket-railsのgemいれる
  2. event.rbでコントローラーをマッピング
  3. JSでマッピングしたルートにデータ送信
  4. Railsで受け取り、すべてのクライアントに送信
  5. JSでイベントをバインドし、受け取ったデータを好きに処理する

JS側で配列処理をする

タスクをko.observableさせたいので、該当するデータを、しかるべき配列の中につっこまないといけません。ここが慣れていなかったので戸惑いました。以下ソースです。

削除の処理

      // todo_destroyイベントを取得
      // dispatcherは「new WebSocketRails("ws://ホスト/websocket");」で、グローバルです。
      dispatcher.bind('todo_destroy', function (removedTodo) {

        $.each(view_model.users(), function() {
          this.todo.remove(function(item) { 

            // itemはobservableなのでitem.id()とする(http://qiita.com/okmttdhr/items/a180b96b5e5e1b30aa1c)
            // idが同じtodoを配列から削除

            return item.id() == removedTodo.id 
          });
        });

      });

編集の処理

完了もこれと同じような感じです。

      // todo_updateイベントを取得
      dispatcher.bind('todo_update', function (updatedTodo) {
        $.each(view_model.users(), function() {

          // 更新の際はremoveのように便利なメソッドがないので(あったら教えて下さい)、eachをネストさせてusersのtodoの中身を見る。

          $.each(this.todo(), function(i, item) {

            // itemはobservableなのでitem.id()とする(http://qiita.com/okmttdhr/items/a180b96b5e5e1b30aa1c)
            // itemはobservableなのでitem.name(updatedTodo.name)のように更新する
            // idが同じtodoに対して更新

            if(item.id() == updatedTodo.id) item.name(updatedTodo.name);
          });
        });
      });

追加の処理


      function TodoConf(data) {
          var self = this;
          self.id = ko.observable(data.id);
          self.name = ko.observable(data.user_id);
          self.del = ko.observable(data.completed);
      }

      // todo_createイベントを取得
      dispatcher.bind('todo_create', function (newTodo) {

        // pushしたデータもobservableにしたいので、生のデータを一度observableに変換する
        var newTodo = new TodoConf(newTodo);

        $.each(view_model.users(), function() {
          // user_idが同じuserに対してtodoを配列に追加
          if (this.id() == newTodo.user_id()) {
            this.todo.push(newTodo);
          };
        });
      });

まとめ

knockoutjsっぽいことといえば、observableにするために配列どうするか考えたことくらいでしょうか。

websocketは案外難しくなく、リアルタイムでDOMをただしく反映するということの方が、複雑になればなるほど難しくなってゆくのかなと思いました。とりあえず、jQueryでやらなくてよかったです。。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2