MeteorのPub/Subを理解するためにできるだけ最小構成で書いてみた
HTML
<head> <title>pub/sub test</title> </head> <body> {{> tweets}} </body> <template name="tweets"> <div id="items-view"> <div id="new-tweet-box"> <input type="text" id="new-tweet" placeholder="New item" /> </div> <ul id="item-list"> {{#each tweets}} {{> tweet_item}} {{/each}} </ul> </div> </template> <template name="tweet_item"> <li class="tweet {{done_class}}"> <div class="tweet-text">{{text}} : {{timestamp}}</div> </li> </template>
// Tweets -- {text: String, // timestamp: Number} Tweets = new Meteor.Collection("tweets"); if (Meteor.isClient) { // Always be subscribed to the todos for the selected list. Meteor.autosubscribe(function () { Meteor.subscribe('tweets'); }); Template.tweets.events = { 'keydown #new-tweet': function(e) { if(e.keyCode == 13) { console.log("Insert : " + text); var text = String(e.target.value || ""); if (text){ Tweets.insert({ text: text, timestamp: (new Date()).getTime() }); } e.target.value = ''; } } } Template.tweets.tweets = function () { return Tweets.find({}, {sort: {timestamp: 1}}); }; } if (Meteor.isServer) { Meteor.publish('tweets', function () { return Tweets.find({}, {sort: {timestamp: 1}}); }); }
Google Drive API (Javascript)を使ってSpreadsheetの内容をCSVで取得する
Google Drive APIだけで行けるかと思ったら無理っぽくて、色々解らなかったのでメモ。
Google APIs ConsoleのServicesからDrive APIをOnにする。
API Accessで
"Client ID(for web applications)"と"Bowser Key"を作る。
"Client ID"の"JavaScript origins"はとりあえず"http://localhost"でいい感じ。
で、こんな感じのコードでできた。
<!DOCTYPE HTML> <html lang="ja"> <head> <meta charset="utf-8"> <title>Export Spreadsheet from Google Drive</title> <script type="text/javascript"> var clientId = '<YOUR_CLIENT_ID>'; var apiKey = '<YOUR_API_KEY>'; var scopes = 'https://www.googleapis.com/auth/drive'; function handleClientLoad() { gapi.client.setApiKey(apiKey); window.setTimeout(checkAuth,1); } function checkAuth() { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult); } function handleAuthResult(authResult) { if (authResult && !authResult.error) { makeApiCall(); } else { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult); } } function makeApiCall() { var accessToken = gapi.auth.getToken().access_token; var xhr = new XMLHttpRequest(); var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=<SPREADSHEET_KEY>&exportFormat=csv"; xhr.open('GET', url); xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); xhr.onload = function() { console.log(xhr.responseText); }; xhr.onerror = function() { console.log("error"); }; xhr.send(); } </script> <script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script> </head> <body> </body> </html>
「とよすすいぞくかん」リリースしました!
Unityの多言語化プラグインを作ってみた
アセットストアで$50で売っているようですが作ってみたので公開します。
多言語化プラグインです。
パラメーターをTというクラスの変数にするためコンパイラによるチェックが行えます。
こちらからダウンロードできます
https://dl.dropbox.com/u/53790848/Unity/Packages/i18n/i18n.unitypackage
使い方:
・メニューのi18nからi18n Windowを選択
・最上部のセルに使いたいローケールを設定
・キー(左端のセル)と値を設定。キーに使える文字は[a-zA-z0-9_]のみ(先頭文字は数字以外)。
・UpdateをクリックするとMessages.xmlとT.csが作成される
・言語の指定はi18n.locale = i18nLocale.ja_JP.ToString();の感じで
・スクリプト中で T.helloのような形で使う(または、T.t("hello"))
・文字列、画像、サウンドに対応
サンプルシーンが入っているので、ご参考ください
Meteor入門 [4] 取り敢えず本家のDocumentを読みながら要約
途中だけど取り敢えず掲載。あとで追記の予定。
Data
Meteorクライアントはインメモリのデータベースキャッシュを持つ
クライアントキャッシュはサーバ側のマスターデータベースの部分的な複製を持つ
チャットシステムの例
サーバは例えば全てのルームとすべてのメッセージの2種類のセットを公開する
クライアントはルームのマスターセットと選択したルームのメッセージのセットに登録する
登録したら、クライアントはキャッシュを早いローカルデータベースとして使う
これでクライアントモデルのコードがとてもシンプルになる
Meteorの分散ドキュメント更新プロトコルはデータベース非依存。
デフォルトではMongoDB APIを使う。
サーバはMongoDBコレクションにドキュメントを格納する
クライアントはクエリと更新がMongoAPIで実装されたキャッシュをつかってキャッシュする
Meteor.publish("chatrooms"); Meteor.publish("messages", function (room_id) { return Messages.find({room] room_id}); }); Meteor.subscribe("chatrooms"); Meteor.subscribe("messages", Chatrooms.find()[0]._id);
ドキュメントの変更は自動的に拡散される。
insert, remove, updateなどはクライアントキャッシュデータで即座に実行される。
同時に、クライアントはサーバーに命令を送り、マスターデータベースも変更される。
通常クライアントとサーバは同意するが、異なるときもある?
(パーミッションのチェックや他のクライアントとのオーバーラップなど)
サーバの結果はクライアントに再公開される
同じ登録をしている全てのクライアントは更新されたドキュメントを受け取る
Messages.insert({room : 2413, text: "hello!"});
これによって、遅延の埋め合わせが実現される。
latency compensation = 遅延の埋め合わせ?
クライアントは必要なデータのフレッシュなコピーを保持し、サーバへのラウンドトリップ時間を待つ必要がない
クライアントがデータを変更した時はローカルで実行されるので、サーバを待たなくて良い
Reactivity
MeteorはReactive Programmingを用いている。
コードをシンプルに素早くかける
コード中で使っているデータが変更されたらそれを利用した結果も自動的に再計算される
Meteor.autosubscribe(function(){ Meteor.subscribe("messages", Session.get("currentRoomId")); }):
Meteor入門 [3] ファイルやディレクトリ構成について
Javascriptでクライアントサイドからサーバサイドまでやれちゃう、IsomorphicでReactive Programmingな新技術Meteorを勉強してみる。の記録。
http://www.meteor.com/main
今回は、ファイルやディレクトリ構成について
ディレクトリについて
Meteorは1つのファイルにサーバとクライアントの両方のコードを書けるわけだけど、分けて書くことも出来るらしい。
あと、サーバが使うファイルとクライアントが使うファイルはディレクトリで分ける。
- serverサブディレクトリに入れたファイルはサーバだけ
- clientサブディレクトリに入れたファイルはクライアントだけ
- publicディレクトリに入れたファイルはRailsやDjangoと同じように普通にサーバから配信される。
- favicon.ico, robots.txtなどはここに入れる。
それ以外は両方にコピーされる。
クライアントに送りたくないコード(例えば、パスワードや認証機構が入っているもの)はserverディレクトリに入れておかなければならない!!
JavascriptとCSSファイル
serverとpublicサブディレクトリ以外のCSSファイル(JSファイルもかな?)は自動的にまとめてクライアントに送られる。
(開発モードではデバッグしやすくするため、Javascript, CSSともに個別のファイルとしてクライアントに送られる)
HTMLファイル
ディレクトリ中の全てのHTMLファイルからhead, body, templateタグのセクションに分けてスキャン。
headとbodyセクションは単一のheadとbodyにまとめて、ページの初回ロード時にクライアントに送信される。
templateセクションは、Javascriptの関数に変換されて、Template名前空間の下に置かれる。
Meteor入門 リンク集
個人的にMeteorを勉強する過程で読んだリンク集です。
Meteor.js : naoyaのはてなダイアリー
http://d.hatena.ne.jp/naoya/20120422/1335109615
Trigger と Stream ベースの Reactive スタイルについて考える : Block Rockin’ Codes
http://d.hatena.ne.jp/Jxck/20120509/1336566474
Meteor について発表してきました : Block Rockin’ Codes
http://d.hatena.ne.jp/Jxck/20120501/1335895469
やさしいFunctional reactive programming(概要編): maoeのブログ
http://d.hatena.ne.jp/maoe/20100109/1263059731