俺の報告

RoomClipを運営するエンジニアの日報(多分)です。

日報 #31 - 俺の適当、ちょっとしたBackbone拡張

俺はブログをやめてないぞ!!
石灰沈着性腱板炎になって腕上がらなかったから更新できなかったんです。
巷では五十肩だとか偽痛風とか言われてますが、
50になったり痛風になったらこんな痛みが連日連夜やってくるっていうのなら、
おれは毎日健康食でいいし、ヨガもやるし、なんか色々飲むよ。
やぁ本当に地獄のような痛みだった。

んで、復帰してシコシコ作業しております。
予定が3日遅れましたが、巻き返しましょう、頑張りましょう。

今日は俺の適当シリーズということで、
BackboneのModel, Collectionの拡張のお話。

Backboneをそのまま使う人は少ないと思います。
その少数派が俺です。
だいたいpluginを使用すると思いますが、まぁぶっちゃけると俺がやりたいことだけでいえば、
pluginいれるほどのことでもなかったりするのも事実です。
ボタン押す→くるくるまわる→状態変わる→ボタンのくるくるもどる。
この程度の実装をそこかしこに仕込むだけなので、どうあったってできちゃうレベルなのです。
それだけやるのに、ましてやMarionette.jsなんて重たいだけだったりします。

そしてもし、今後物凄い勢いでヌルヌル動くうぇぶあぷりけーしょんを作るのであれば、
Angularなり他のFWと一緒に再度比較とあいなるわけで、
じゃぁなんのためにJSのFWいれてるのかって?

単純に「整理された管理」を実現するためです。
というわけで、割合きれいそうなBackboneを使っているのですね。

さて、jsをたーくさんのファイルに切って管理して、model部分の更新をトリガで繋ぐ世界観には随分慣れ親しんだわけですが、とはいえ、裸のBackboneには限界が有るのも事実。

ということで、とりあえず僕が勝手に拡張している部分だけご紹介します。

window.custom.Backbone.Collection = Backbone.Collection.extend({
          _lock: false,
          _error: false,

          lock: function(state,method){
               if (_.isUndefined(state)) {
                    // getter
                    return this._lock;
               } else {
                    // setter
                    this._lock=state;
                    if (_.isUndefined(method))
                         this.trigger('lock',[this]);
                    else
                         this.trigger('lock:'+method,this);
               }
          },

          load_error: function(state,method,message){
               if (_.isUndefined(message))
                    message=null;

               if (_.isUndefined(state)) {
                    // getter
                    return this._error;
               } else {
                    // setter
                    this._error=state;
                    if (_.isUndefined(method))
                         this.trigger('load_error',[this,message]);
                    else
                         this.trigger('load_error:'+method,[this,message]);
               }
          },

});

わかりやすさ追求でシンプルな紹介にさせて頂いてます。
とっても簡単で、要はCollectionにlockという概念と、errorという概念を付与させました。
冒頭述べたとおり、大体うちのjsシーンというのは、
dbに対してajaxで同期した情報持ってきてmodelに突っ込む、
その間htmlはローディング状態、完了状態、エラー状態を行き来するだけ。    っつぅ感じなので、lockメソッドを用意し、対象となるcollection(まぁmodelでもよし)が同期対象になっているかどうかをフラグ建てしたわけですね。
こうすれば、むっちゃ簡単な話、こんな感じに書けば良いと。

// lockされていれば処理しません
if (!collection.lock())
  return;

// lockします
collection.lock(true, 'huge;);

$.getJSON(…. function(json){
  // lock解除します
  collection.lock(false, 'hoge');
});

こーしといて、ボタンビューでは、

// lockをキャッチする
view.listenTo(collection, 'lock:hoge', view.render_loading);

みたいな感じで受けておけばローディング画面のイベント処理は整理されます。
案外便利ですが、きっともっとイケてるシステムがマリオネットやプラグインにはあるんだろうなぁと思いながら面倒だから実装しちゃったという良くない例でした。

さぁ頑張って作業進めましょう。